mynixos-config/modules/backups.nix
2024-11-26 13:34:55 +01:00

87 lines
2.5 KiB
Nix

{
config,
globals,
lib,
...
}:
let
inherit (lib)
attrValues
flip
mkIf
mkMerge
mkOption
types
;
in
{
options.backups.storageBoxes = mkOption {
description = "Backups to Hetzner Storage Boxes using restic";
default = { };
type = types.attrsOf (
types.submodule (submod: {
options = {
name = mkOption {
description = "The name of the storage box to backup to. The box must be defined in the globals. Defaults to the attribute name.";
default = submod.config._module.args.name;
type = types.str;
};
subuser = mkOption {
description = "The name of the storage box subuser as defined in the globals, mapping this user to a subuser id.";
type = types.str;
};
paths = mkOption {
description = "The paths to backup.";
type = types.listOf types.path;
};
};
})
);
};
config = mkIf (config.backups.storageBoxes != { }) {
age.secrets.restic-encryption-password.generator.script = "alnum";
age.secrets.restic-ssh-privkey.generator.script = "ssh-ed25519";
services.restic.backups = mkMerge (
flip map (attrValues config.backups.storageBoxes) (boxCfg: {
"storage-box-${boxCfg.name}" = {
hetznerStorageBox =
let
box = globals.hetzner.storageboxes.${boxCfg.name};
in
{
enable = true;
inherit (box) mainUser;
inherit (box.users.${boxCfg.subuser}) subUid path;
sshAgeSecret = "restic-ssh-privkey";
};
# A) We need to backup stuff from other users, so run as root.
# B) We also need to be root because the ssh key will only
# be accessible to root so whatever service is running cannot
# just access our backup server.
user = "root";
inherit (boxCfg) paths;
timerConfig = {
OnCalendar = "06:15";
RandomizedDelaySec = "3h";
Persistent = true;
};
initialize = true;
passwordFile = config.age.secrets.restic-encryption-password.path;
# We cannot prune ourselves, since the remote repository will be append-only
# pruneOpts = [
# "--keep-daily 14"
# "--keep-weekly 7"
# "--keep-monthly 12"
# "--keep-yearly 75"
# ];
};
})
);
};
}