# Importing this adds a daily borg backup job to a node.
# It has all the common config and keys, and can be configured
# to back up more (or entirely different) folders.


{ lib, config, pkgs, ...}:
let
  cfg = config.services.private-storage.borgbackup;
  inherit (config.grid) publicKeyPath privateKeyPath;

  # Get a per-host number so backup jobs don't all run at the
  # same time.
  ip-util = import ../../nixos/lib/ip-util.nix;
  backupDelay = with builtins; bitAnd (ip-util.fromHexString
    (hashString "md5" config.networking.hostName)) 15;

in {
  options.services.private-storage.borgbackup = {
    enable = lib.mkEnableOption "Borgbackup daily backup job";
    paths = lib.mkOption {
      type = lib.types.listOf lib.types.str;
      description = ''
        A list of directories to back up using Borg.
      '';
      default = [ "/storage" ];
    };
  };

  config = lib.mkIf cfg.enable {
    deployment = {
      secrets = {
        "borgbackup-passphrase" = {
          # The passphrase is used to encrypt the repo key
          # https://borgbackup.readthedocs.io/en/stable/usage/init.html
          destination = "/run/keys/borgbackup/passphrase";
          source = "${privateKeyPath}/borgbackup.passphrase";
        };
        "borgbackup-appendonly-ssh-key" = {
          # The ssh key is used to authenticate to the remote repo server
          destination = "/run/keys/borgbackup/ssh-key";
          source = "${privateKeyPath}/borgbackup.ssh-key";
        };
      };
    };

    services.borgbackup.jobs = {
      daily = {
        paths = cfg.paths;
        repo = lib.fileContents "${publicKeyPath}/borgbackup/${config.networking.hostName}.repopath";
        doInit = false;
        encryption = {
          mode = "repokey-blake2";
          passCommand = "cat /run/keys/borgbackup/passphrase";
        };
        environment = {
          BORG_RSH = "ssh -i /run/keys/borgbackup/ssh-key -o StrictHostKeyChecking=accept-new";
        };

	# Output statistics after uploading a backup set
	extraCreateArgs = "--stats --json";
	# All logs in JSON to help Prometheus/Grafana
	extraArgs = "--log-json";

        # Ciphertext doesn't compress well
        compression = "none";

        # Start the backup at a different time per machine,
        # and not at the full hour, but somewhat later
        startAt = "*-*-* " + toString backupDelay + ":22:11 UTC";
      };
    };

    # Check repo once a month
    systemd.services.borgbackup-check-repo = {
      # Once a month, 3h after last backup started
      startAt = "*-*-" + toString backupDelay + " 18:33:22 UTC";
      path = [ pkgs.borgbackup ];
      environment = {
        BORG_PASSCOMMAND = "cat /run/keys/borgbackup/passphrase";
        BORG_RSH = "ssh -i /run/keys/borgbackup/ssh-key -o StrictHostKeyChecking=accept-new";
        BORG_REPO = lib.fileContents "${publicKeyPath}/borgbackup/${config.networking.hostName}.repopath";
      };
      script = ''${pkgs.borgbackup}/bin/borg check'';
    };
  };
}