nixos/users/modules/restic-backup.nix

91 lines
2.6 KiB
Nix

# Restic user backups
#
# This _assumes_ a few things:
# - There is a sops.secrets with the name "restic-backup-USERNAME"
# - That the repository is actually reachable, which is a little flaky still
{
nixosConfig,
pkgs,
lib,
config,
...
}: let
resticCmd = "${pkgs.restic}/bin/restic";
inherit (config.home) username;
repository = "s3:https://s3.tammena.me/restic/${username}";
passwordFile = nixosConfig.sops.secrets."restic-backup-${username}".path;
defaultPruneOpts = [
"--keep-hourly 5"
"--keep-daily 5"
"--keep-weekly 5"
"--keep-monthly 5"
"--keep-yearly 5"
];
sessionVars = {
RESTIC_REPOSITORY = repository;
RESTIC_PASSWORD_FILE = passwordFile;
};
cfg = config.services.restic;
in {
options.services.restic = with lib; {
enable = mkEnableOption "restic backup service";
paths = mkOption {
type = types.listOf types.str;
default = [];
description = "Paths to backup";
};
pruneOpts = mkOption {
type = types.listOf types.str;
default = defaultPruneOpts;
description = "Additional options for pruning";
};
};
config = lib.mkIf cfg.enable {
# Add restic for the user (they will need to initialize the repo)
home.packages = [pkgs.restic];
# Add the above env variables, so that using restic is easy for them
home.sessionVariables = sessionVars;
# Create a systemd service for the backup
systemd.user.services.restic-backups-to-faunus-ater = {
Unit = {
Description = "Backup to faunus-ater using restic";
After = ["network.target"];
};
Service = {
Type = "oneshot";
ExecStart = [
# Start by backing up every directory requested
"${resticCmd} backup --retry-lock 5m --cache-dir=%C/restic-backups-to-faunus-ater ${
toString cfg.paths
}"
# Prune old backups to keep the repo tidy
"${resticCmd} forget --prune ${toString cfg.pruneOpts}"
];
RuntimeDirectory = "restic-backups-to-faunus-ater";
CacheDirectory = "restic-backups-to-faunus-ater";
CacheDirectoryMode = "0700";
# Convert the above map of environment variables into a list
# of "KEY=VALUE" entries
Environment =
builtins.attrValues
(builtins.mapAttrs (k: v: "${k}=${v}") sessionVars);
};
};
# Run the above service every hour
systemd.user.timers.restic-backups-to-faunus-ater = {
Unit = {Description = "Run restic backups every hour";};
Install = {WantedBy = ["timers.target"];};
Timer = {
OnCalendar = "hourly";
RandomizedDelaySec = "1800";
};
};
};
}