{ config, lib, options, pkgs, ... }: let cfg = config.kyouma.restic; in { options.kyouma.restic = let inherit (lib) mkOption types; in { inherit (options.services.restic.backups.type.getSubOptions []) timerConfig backupPrepareCommand backupCleanupCommand; enable = lib.mkEnableOption "Enable restic backup"; paths = mkOption { description = "paths to backup"; type = with types; listOf path; default = []; }; pruneOpts = mkOption { description = "paths to backup"; type = with types; listOf str; default = [ "--keep-hourly 24" "--keep-daily 14" "--keep-weekly 8" "--keep-monthly 12" ]; }; remote = mkOption { description = "restic remote to use"; type = types.nonEmptyStr; default = "zh3485.rsync.net"; }; remoteUser = mkOption { description = "remote ssh user"; type = types.nonEmptyStr; default = ""; }; user = mkOption { description = "user who runs the backup job"; type = types.nonEmptyStr; default = "root"; }; repo = mkOption { description = "restic repo"; type = types.nonEmptyStr; default = "${config.networking.hostName}-backup"; }; }; config = lib.mkIf cfg.enable { sops.secrets."restic/${cfg.remoteUser}/password" = { sopsFile = ../../secrets/restic/${cfg.remoteUser}.yaml; }; sops.secrets."restic/${cfg.remoteUser}/id_ed25519" = { sopsFile = ../../secrets/restic/${cfg.remoteUser}.yaml; }; services.restic.backups."${config.networking.hostName}-${cfg.remote}" = { inherit (cfg) paths user pruneOpts timerConfig backupPrepareCommand backupCleanupCommand; initialize = true; repository = "sftp:${cfg.remoteUser}@${cfg.remote}:${cfg.repo}"; passwordFile = config.sops.secrets."restic/${cfg.remoteUser}/password".path; extraBackupArgs = [ "--compression=max" "--pack-size=128" "--read-concurrency=8" ]; extraOptions = let knownHost = pkgs.writeText "${cfg.remote}-known-host" (builtins.readFile ./${cfg.remote}/ssh_host_ed25519_key.pub); sshKey = config.sops.secrets."restic/${cfg.remoteUser}/id_ed25519".path; in [ "sftp.command='ssh ${cfg.remoteUser}@${cfg.remote} -i ${sshKey} -o UserKnownHostsFile=${knownHost} -s sftp'" ]; }; }; }