106 lines
3.0 KiB
Nix
106 lines
3.0 KiB
Nix
{
|
|
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;
|
|
};
|
|
}
|