aboutsummaryrefslogtreecommitdiffstats
path: root/modules/by-name
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/by-name/ba/backup/module.nix138
-rw-r--r--modules/by-name/ba/backup/secrets/local/repository_password.age20
-rw-r--r--modules/by-name/ba/backup/secrets/storagebox/repository_password.age (renamed from modules/common/secrets/backup/privatePassword.age)0
-rw-r--r--modules/by-name/ba/backup/secrets/storagebox/ssh_key.age (renamed from modules/common/secrets/backup/privateSshKey.age)0
4 files changed, 121 insertions, 37 deletions
diff --git a/modules/by-name/ba/backup/module.nix b/modules/by-name/ba/backup/module.nix
index 3e07fbd1..8d7d6bbb 100644
--- a/modules/by-name/ba/backup/module.nix
+++ b/modules/by-name/ba/backup/module.nix
@@ -16,40 +16,66 @@
cfg = config.soispha.services.backup;
in {
options.soispha.services.backup = {
- enable = lib.mkEnableOption "backups via restic to a storagebox";
+ storagebox = {
+ enable = lib.mkEnableOption "remote backups";
+ user = lib.mkOption {
+ type = lib.types.str;
+ description = "The storagebox-user to use";
+ example = "u384702-sub2";
+ };
- user = lib.mkOption {
- type = lib.types.str;
- description = "The storagebox-user to use";
- example = "u384702-sub2";
- };
- privateSshKey = lib.mkOption {
- type = lib.types.path;
- description = "The age-encrypted ssh-key, passed to agenix";
+ sshKey = lib.mkOption {
+ type = lib.types.path;
+ description = "The age-encrypted ssh-key, passed to agenix";
+ default = ./secrets/storagebox/ssh_key.age;
+ };
+
+ repositoryPassword = lib.mkOption {
+ type = lib.types.path;
+ description = "The age-encrypted restic password, passed to agenix";
+ default = ./secrets/storagebox/repository_password.age;
+ };
};
- privatePassword = lib.mkOption {
- type = lib.types.path;
- description = "The age-encrypted restic password, passed to agenix";
+
+ local = {
+ enable = lib.mkEnableOption "local backups";
+
+ repositoryPassword = lib.mkOption {
+ type = lib.types.path;
+ description = "The age-encrypted restic password, passed to agenix";
+ default = ./secrets/local/repository_password.age;
+ };
+
+ backupDiskUuid = lib.mkOption {
+ example = lib.literalExpression "d1d20ae7-3d8a-44da-86da-677dbbb10c89";
+ description = "The UUID of the backup disk";
+ };
};
};
- config = lib.mkIf cfg.enable {
+ config = {
age.secrets = {
- resticpass = {
- file = cfg.privatePassword;
+ resticStorageboxSshKey = lib.mkIf cfg.storagebox.enable {
+ file = cfg.storagebox.sshKey;
+ mode = "0700";
+ owner = "root";
+ group = "root";
+ };
+ resticStorageboxRepositoryPassword = lib.mkIf cfg.storagebox.enable {
+ file = cfg.storagebox.repositoryPassword;
mode = "0700";
owner = "root";
group = "root";
};
- resticssh = {
- file = cfg.privateSshKey;
+ resticLocalRepositoryPassword = lib.mkIf cfg.local.enable {
+ file = cfg.local.repositoryPassword;
mode = "0700";
owner = "root";
group = "root";
};
};
- soispha.programs.ssh = {
+ soispha.programs.ssh = lib.mkIf cfg.storagebox.enable {
enable = true;
rootKnownHosts = {
"[u459143-sub1.your-storagebox.de]:23" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICf9svRenC/PLKIL9nk6K/pxQgoiFC41wTNvoIncOxs";
@@ -59,30 +85,68 @@ in {
services.restic.backups = let
snapshotDir = "/srv/last_snapshot";
homeDir = "${snapshotDir}/home";
+
+ paths = [
+ snapshotDir
+ ];
+ exclude = [
+ "${homeDir}/soispha/.cache"
+ ];
+ extraBackupArgs = [
+ "--verbose=2"
+ ];
+
+ backupPrepareCommand = extra:
+ # bash
+ extra
+ + ''
+ [ -d "${snapshotDir}" ] && ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume delete "${snapshotDir}"
+
+ # -r := Make the snapshot read-only
+ ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume snapshot -r /srv "${snapshotDir}";
+ '';
in {
- storagebox = {
+ local = let
+ backupMountPoint = "/run/media/${cfg.local.backupDiskUuid}";
+ in
+ lib.mkIf cfg.local.enable {
+ inhibitsSleep = true;
+ initialize = true;
+
+ inherit paths exclude extraBackupArgs;
+
+ # TODO: We could maybe use systemd's built-in system for this mounting. <2025-05-01>
+ backupPrepareCommand =
+ backupPrepareCommand
+ # bash
+ ''
+ set -xeu
+ ${lib.getExe' pkgs.util-linux "mount"} --mkdir "/dev/disk/by-uuid/${cfg.local.backupDiskUuid}" "${backupMountPoint}"
+ '';
+ backupCleanupCommand =
+ # bash
+ ''
+ ${lib.getExe' pkgs.util-linux "umount"} "${backupMountPoint}"
+ '';
+
+ passwordFile = config.age.secrets.resticLocalRepositoryPassword.path;
+
+ repository = "${backupMountPoint}/restic-backup-data/";
+
+ # Start on demand.
+ timerConfig = null;
+ };
+
+ storagebox = lib.mkIf cfg.storagebox.enable {
+ inhibitsSleep = true;
initialize = true;
- backupPrepareCommand =
- # bash
- ''
- [ -d "${snapshotDir}" ] && ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume delete "${snapshotDir}"
- # -r := Make the snapshot read-only
- ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume snapshot -r /srv "${snapshotDir}";
- '';
- paths = [
- snapshotDir
- ];
- exclude = [
- "${homeDir}/soispha/.cache"
- ];
- extraBackupArgs = [
- "--verbose=2"
- ];
+ inherit paths exclude extraBackupArgs;
+ backupPrepareCommand = backupPrepareCommand "";
- passwordFile = config.age.secrets.resticpass.path;
+ passwordFile = config.age.secrets.resticStorageboxRepositoryPassword.path;
extraOptions = [
- "rclone.program='ssh -p 23 ${cfg.user}@${cfg.user}.your-storagebox.de -i ${config.age.secrets.resticssh.path} command_forced_on_remote'"
+ "rclone.program='ssh -p 23 ${cfg.storagebox.user}@${cfg.storagebox.user}.your-storagebox.de -i ${config.age.secrets.resticStorageboxSshKey.path} command_forced_on_remote'"
];
# This setting is normally passed to rclone, but we force
diff --git a/modules/by-name/ba/backup/secrets/local/repository_password.age b/modules/by-name/ba/backup/secrets/local/repository_password.age
new file mode 100644
index 00000000..b1508e49
--- /dev/null
+++ b/modules/by-name/ba/backup/secrets/local/repository_password.age
@@ -0,0 +1,20 @@
+-----BEGIN AGE ENCRYPTED FILE-----
+YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqVCtBZzNBWFlxQnhlb3c2
+NG0xMjV3V2hQUWhNb01ROGpFbzM0c3NjRWlvCjRqMTdxNlNsY1lDM2VCUGRjcldZ
+SUhScGRSejY3TFlwVjlweTRERkU4ZTQKLT4gc3NoLWVkMjU1MTkgelpFb25nIGtj
+cVN4RzFseTJCVXhOc0tEWi96ckpGQjhNdUZrb1FVWnJ6TU1vSHZCMUkKc1JwM2Ir
+TzNzZEV5VEE4QUp4cDdTNWZvTFlZR0tUbUFZTnNEZE1McnhISQotPiBzc2gtZWQy
+NTUxOSA3SGZGVXcgYVQzRHdaa1NYUUpLODUyL0orV3d4Z1o1V2hhekZXVWFzNW50
+enhSYnlWbwpzbnZwK1dSczJ5SGZsRjNyRWZraUcreWlBakZOZkVyZ01CWml5V0E4
+TzY4Ci0+ICpMUC1ncmVhc2UgV0IKUTZVMzR1QTVGdWRyNWprVVpjaWhCTTFSRzY3
+bHVtdHpJQXlWQVFHZ3FzbkZncHRsQnJIaHlEekl5ZE15Sko0YQpSVEUKLS0tIGFy
+N1Y2OUREY1NOL2xPODd4Y3Y4Wk83NFJ5ZVBpNnJYelo3RmZPL1V4Q28KcA+6qt2d
+LrL0FS279XL1uqSeXiDdBBBh5i951dRx9ML33g7IoQxaGqSWU0yP/y7fcSp3B/rT
+/alQGRL/uYnCS2z8zCngr2YCQBXAI8bOgf+th7fzc15FXNB14WMGvrCVRB8Rr6JZ
+itTxcAebY192xeINJG269iL6Ef0YrmZLUufKQ9lcVob/G32tG0vxSbSBBx3asf7y
+toiNdlXpxJPrIpFx5mc3dnkaXCTSRuXjiAqnncW/HNxovCI90sY3dyL+XRC8iEOD
+sql7C7jUUvLubptk1gGW5pHmGvqeCLr+fJ6XrVqXE5VxOSbzvSUsdS84WOBInLiO
+V36aUtthEzdRXd81P/n7U26O93GWpIwzctu0WwSHHHsPKhxqFY4RuWa3mO4Zk6fu
+O6fsYnpAqYiCUd/k2zKrDtLosTnwuwc7Vm1glm4DEEtvteVibw47SR1LLfUds5XL
+j1OR7Z6/ljIEKPjE1a81pQjYRfHDUtceXUvrlL6iCID30zU=
+-----END AGE ENCRYPTED FILE-----
diff --git a/modules/common/secrets/backup/privatePassword.age b/modules/by-name/ba/backup/secrets/storagebox/repository_password.age
index a2aa984a..a2aa984a 100644
--- a/modules/common/secrets/backup/privatePassword.age
+++ b/modules/by-name/ba/backup/secrets/storagebox/repository_password.age
diff --git a/modules/common/secrets/backup/privateSshKey.age b/modules/by-name/ba/backup/secrets/storagebox/ssh_key.age
index a7f30c7c..a7f30c7c 100644
--- a/modules/common/secrets/backup/privateSshKey.age
+++ b/modules/by-name/ba/backup/secrets/storagebox/ssh_key.age