{ lib, config, ... }: let cfg = config.cloud-host-backup; in { options = { cloud-host-backup = { enable = lib.mkEnableOption "pull backups from cloud hosts via SFTP"; hosts = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule { options = { hostname = lib.mkOption { type = lib.types.str; description = "SSH hostname of the cloud host"; }; username = lib.mkOption { type = lib.types.str; default = config.secrets.username; description = "SSH username for the cloud host"; }; remotePath = lib.mkOption { type = lib.types.str; default = "/home"; description = "Remote path to backup"; }; excludePatterns = lib.mkOption { type = lib.types.listOf lib.types.str; description = "Exclude patterns for restic"; default = [ ]; }; }; } ); default = { }; example = { andromache = { hostname = "andromache.local"; }; }; }; b2Bucket = lib.mkOption { type = lib.types.str; description = "B2 bucket name"; }; passwordFile = lib.mkOption { type = lib.types.str; default = config.sops.secrets."restic_password".path; }; sshKeyFile = lib.mkOption { type = lib.types.str; default = "/home/${config.secrets.username}/.ssh/id_ed25519"; description = "SSH private key file for authentication"; }; }; }; config = lib.mkIf cfg.enable { sops.templates = lib.mapAttrs' ( hostName: hostCfg: lib.nameValuePair "restic/repo-cloud-${hostName}" { content = "b2:${config.sops.placeholder."b2_bucket_name"}:${hostName}/"; } ) cfg.hosts; services.restic.backups = lib.mapAttrs' ( hostName: hostCfg: lib.nameValuePair "cloud-${hostName}" { repositoryFile = config.sops.templates."restic/repo-cloud-${hostName}".path; passwordFile = cfg.passwordFile; paths = [ "sftp:${hostCfg.username}@${hostCfg.hostname}:${hostCfg.remotePath}" ]; timerConfig = { OnCalendar = "daily"; Persistent = true; }; initialize = true; extraBackupArgs = [ "--one-file-system" ] ++ lib.optional (hostCfg.excludePatterns != [ ]) ( builtins.concatStringsSep " " (map (p: "--exclude ${p}") hostCfg.excludePatterns) ); pruneOpts = [ "--keep-daily 7" "--keep-weekly 4" "--keep-monthly 6" "--keep-yearly 1" ]; environmentFile = config.sops.templates."restic/b2-env".path; extraOptions = [ "sftp.command=ssh -i ${cfg.sshKeyFile} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ]; } ) cfg.hosts; }; }