diff options
-rw-r--r-- | hosts/vidhar/borg/default.nix | 61 | ||||
-rw-r--r-- | modules/borgsnap/borgsnap/borgsnap/__main__.py (renamed from hosts/vidhar/borg/borgsnap/borgsnap/__main__.py) | 1 | ||||
-rw-r--r-- | modules/borgsnap/borgsnap/setup.py (renamed from hosts/vidhar/borg/borgsnap/setup.py) | 0 | ||||
-rw-r--r-- | modules/borgsnap/default.nix | 106 | ||||
-rw-r--r-- | modules/zfssnap/default.nix | 18 | ||||
-rw-r--r-- | modules/zfssnap/zfssnap/zfssnap/__main__.py | 3 |
6 files changed, 135 insertions, 54 deletions
diff --git a/hosts/vidhar/borg/default.nix b/hosts/vidhar/borg/default.nix index fe62c956..8d0b46ef 100644 --- a/hosts/vidhar/borg/default.nix +++ b/hosts/vidhar/borg/default.nix | |||
@@ -3,7 +3,7 @@ | |||
3 | with lib; | 3 | with lib; |
4 | 4 | ||
5 | let | 5 | let |
6 | sshConfig = pkgs.writeText "config" '' | 6 | sshConfig = '' |
7 | Include /etc/ssh/ssh_config | 7 | Include /etc/ssh/ssh_config |
8 | 8 | ||
9 | ControlMaster auto | 9 | ControlMaster auto |
@@ -33,7 +33,7 @@ let | |||
33 | # StateDirectory = "borg"; | 33 | # StateDirectory = "borg"; |
34 | RuntimeDirectory = "copy-borg"; | 34 | RuntimeDirectory = "copy-borg"; |
35 | Environment = [ | 35 | Environment = [ |
36 | "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${sshConfig}\"" | 36 | "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${pkgs.writeText "config" sshConfig}\"" |
37 | "BORG_BASE_DIR=/var/lib/borg" | 37 | "BORG_BASE_DIR=/var/lib/borg" |
38 | "BORG_CONFIG_DIR=/var/lib/borg/config" | 38 | "BORG_CONFIG_DIR=/var/lib/borg/config" |
39 | "BORG_CACHE_DIR=/var/lib/borg/cache" | 39 | "BORG_CACHE_DIR=/var/lib/borg/cache" |
@@ -74,63 +74,20 @@ let | |||
74 | copy | 74 | copy |
75 | 75 | ||
76 | wrapProgram $out/bin/copy \ | 76 | wrapProgram $out/bin/copy \ |
77 | --prefix PATH : ${makeBinPath (with pkgs; [config.boot.zfs.package util-linux borgbackup])}:${config.security.wrapperDir} | ||
78 | ''; | ||
79 | }); | ||
80 | |||
81 | borgsnap = flakeInputs.mach-nix.lib.${config.nixpkgs.system}.buildPythonPackage rec { | ||
82 | pname = "borgsnap"; | ||
83 | src = ./borgsnap; | ||
84 | version = "0.0.0"; | ||
85 | ignoreDataOutdated = true; | ||
86 | |||
87 | requirements = '' | ||
88 | atomicwrites | ||
89 | pyprctl | ||
90 | python-unshare | ||
91 | python-dateutil | ||
92 | ''; | ||
93 | postInstall = '' | ||
94 | wrapProgram $out/bin/borgsnap \ | ||
95 | --prefix PATH : ${makeBinPath (with pkgs; [util-linux borgbackup])}:${config.security.wrapperDir} | 77 | --prefix PATH : ${makeBinPath (with pkgs; [util-linux borgbackup])}:${config.security.wrapperDir} |
96 | ''; | 78 | ''; |
97 | 79 | }); | |
98 | providers.python-unshare = "nixpkgs"; | ||
99 | overridesPre = [ | ||
100 | (self: super: { python-unshare = super.python-unshare.overrideAttrs (oldAttrs: { name = "python-unshare-0.2.1"; version = "0.2.1"; }); }) | ||
101 | ]; | ||
102 | |||
103 | _.tomli.buildInputs.add = with pkgs."python3Packages"; [ flit-core ]; | ||
104 | }; | ||
105 | in { | 80 | in { |
106 | config = { | 81 | config = { |
107 | services.zfssnap.config.exec = { | 82 | services.borgsnap = { |
108 | check = "${borgsnap}/bin/borgsnap -vv --target yggdrasil.borgbase:repo --archive-prefix yggdrasil.vidhar. check --cache-file /run/zfssnap-prune/archives-cache.json"; | 83 | enable = true; |
109 | cmd = "${borgsnap}/bin/borgsnap -vv --target yggdrasil.borgbase:repo --archive-prefix yggdrasil.vidhar. create"; | ||
110 | 84 | ||
111 | halfweekly = "8"; | 85 | target = "yggdrasil.borgbase:repo"; |
112 | monthly = "-1"; | 86 | inherit sshConfig; |
87 | keyfile = config.sops.secrets."yggdrasil.borgkey".path; | ||
113 | }; | 88 | }; |
114 | 89 | ||
115 | systemd.services = { | 90 | systemd.services = listToAttrs (map copyService [{ repo = "/srv/backup/borg/jotnar"; repoEscaped = "srv-backup-borg-jotnar"; }]); |
116 | "zfssnap-prune" = { | ||
117 | serviceConfig = { | ||
118 | Environment = [ | ||
119 | "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${sshConfig}\"" | ||
120 | "BORG_BASE_DIR=/var/lib/borg" | ||
121 | "BORG_CONFIG_DIR=/var/lib/borg/config" | ||
122 | "BORG_CACHE_DIR=/var/lib/borg/cache" | ||
123 | "BORG_SECURITY_DIR=/var/lib/borg/security" | ||
124 | "BORG_KEYS_DIR=/var/lib/borg/keys" | ||
125 | "BORG_KEY_FILE=${config.sops.secrets."yggdrasil.borgkey".path}" | ||
126 | "BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes" | ||
127 | "BORG_HOSTNAME_IS_UNIQUE=yes" | ||
128 | ]; | ||
129 | RuntimeDirectory = "zfssnap-prune"; | ||
130 | }; | ||
131 | }; | ||
132 | } // listToAttrs (map copyService [{ repo = "/srv/backup/borg/jotnar"; repoEscaped = "srv-backup-borg-jotnar"; }]); | ||
133 | |||
134 | 91 | ||
135 | services.borgbackup.repos.jotnar = { | 92 | services.borgbackup.repos.jotnar = { |
136 | path = "/srv/backup/borg/jotnar"; | 93 | path = "/srv/backup/borg/jotnar"; |
diff --git a/hosts/vidhar/borg/borgsnap/borgsnap/__main__.py b/modules/borgsnap/borgsnap/borgsnap/__main__.py index 15bf50c8..4b50cf80 100644 --- a/hosts/vidhar/borg/borgsnap/borgsnap/__main__.py +++ b/modules/borgsnap/borgsnap/borgsnap/__main__.py | |||
@@ -357,6 +357,7 @@ def main(): | |||
357 | sys.excepthook = log_exceptions | 357 | sys.excepthook = log_exceptions |
358 | 358 | ||
359 | parser = argparse.ArgumentParser(prog='borgsnap') | 359 | parser = argparse.ArgumentParser(prog='borgsnap') |
360 | parser.add_argument('--verbosity', dest='log_level', action='append') | ||
360 | parser.add_argument('--verbose', '-v', dest='log_level', action='append_const', const=-1) | 361 | parser.add_argument('--verbose', '-v', dest='log_level', action='append_const', const=-1) |
361 | parser.add_argument('--quiet', '-q', dest='log_level', action='append_const', const=1) | 362 | parser.add_argument('--quiet', '-q', dest='log_level', action='append_const', const=1) |
362 | parser.add_argument('--target', metavar='REPO', default='yggdrasil.borgbase:repo') | 363 | parser.add_argument('--target', metavar='REPO', default='yggdrasil.borgbase:repo') |
diff --git a/hosts/vidhar/borg/borgsnap/setup.py b/modules/borgsnap/borgsnap/setup.py index 76356bfc..76356bfc 100644 --- a/hosts/vidhar/borg/borgsnap/setup.py +++ b/modules/borgsnap/borgsnap/setup.py | |||
diff --git a/modules/borgsnap/default.nix b/modules/borgsnap/default.nix new file mode 100644 index 00000000..f4c0eec4 --- /dev/null +++ b/modules/borgsnap/default.nix | |||
@@ -0,0 +1,106 @@ | |||
1 | { config, pkgs, lib, flakeInputs, hostName, ... }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | borgsnap = flakeInputs.mach-nix.lib.${config.nixpkgs.system}.buildPythonPackage rec { | ||
7 | pname = "borgsnap"; | ||
8 | src = ./borgsnap; | ||
9 | version = "0.0.0"; | ||
10 | ignoreDataOutdated = true; | ||
11 | |||
12 | requirements = '' | ||
13 | atomicwrites | ||
14 | pyprctl | ||
15 | python-unshare | ||
16 | python-dateutil | ||
17 | ''; | ||
18 | postInstall = '' | ||
19 | wrapProgram $out/bin/borgsnap \ | ||
20 | --prefix PATH : ${makeBinPath (with pkgs; [config.boot.zfs.package util-linux borgbackup])}:${config.security.wrapperDir} | ||
21 | ''; | ||
22 | |||
23 | providers.python-unshare = "nixpkgs"; | ||
24 | overridesPre = [ | ||
25 | (self: super: { python-unshare = super.python-unshare.overrideAttrs (oldAttrs: { name = "python-unshare-0.2.1"; version = "0.2.1"; }); }) | ||
26 | ]; | ||
27 | |||
28 | _.tomli.buildInputs.add = with pkgs."python3Packages"; [ flit-core ]; | ||
29 | }; | ||
30 | |||
31 | cfg = config.services.borgsnap; | ||
32 | in { | ||
33 | options = { | ||
34 | services.borgsnap = { | ||
35 | enable = mkEnableOption "borgsnap service"; | ||
36 | |||
37 | target = mkOption { | ||
38 | type = types.str; | ||
39 | }; | ||
40 | |||
41 | archive-prefix = mkOption { | ||
42 | type = types.str; | ||
43 | default = "yggdrasil.${hostName}."; | ||
44 | }; | ||
45 | |||
46 | extraConfig = mkOption { | ||
47 | type = with types; attrsOf str; | ||
48 | default = { | ||
49 | halfweekly = "8"; | ||
50 | monthly = "-1"; | ||
51 | }; | ||
52 | }; | ||
53 | |||
54 | verbosity = mkOption { | ||
55 | type = types.int; | ||
56 | default = config.services.zfssnap.verbosity; | ||
57 | }; | ||
58 | |||
59 | sshConfig = mkOption { | ||
60 | type = with types; nullOr str; | ||
61 | default = null; | ||
62 | }; | ||
63 | |||
64 | keyfile = mkOption { | ||
65 | type = with types; nullOr str; | ||
66 | default = null; | ||
67 | }; | ||
68 | |||
69 | extraCreateArgs = mkOption { | ||
70 | type = with types; listOf str; | ||
71 | default = []; | ||
72 | }; | ||
73 | extraCheckArgs = mkOption { | ||
74 | type = with types; listOf str; | ||
75 | default = []; | ||
76 | }; | ||
77 | }; | ||
78 | }; | ||
79 | |||
80 | config = mkIf cfg.enable { | ||
81 | warnings = mkIf (!config.services.zfssnap.enable) [ | ||
82 | "borgsnap will do nothing if zfssnap is not enabled" | ||
83 | ]; | ||
84 | |||
85 | services.zfssnap.config.exec = { | ||
86 | check = "${borgsnap}/bin/borgsnap --verbosity=${toString cfg.verbosity} --target ${escapeShellArg cfg.target} --archive-prefix ${escapeShellArg cfg.archive-prefix} check --cache-file /run/zfssnap-prune/archives-cache.json ${escapeShellArgs cfg.extraCheckArgs}"; | ||
87 | cmd = "${borgsnap}/bin/borgsnap --verbosity=${toString cfg.verbosity} --target ${escapeShellArg cfg.target} --archive-prefix ${escapeShellArg cfg.archive-prefix} create ${escapeShellArgs cfg.extraCreateArgs}"; | ||
88 | } // cfg.extraConfig; | ||
89 | |||
90 | systemd.services."zfssnap-prune" = { | ||
91 | serviceConfig = { | ||
92 | Environment = [ | ||
93 | "BORG_BASE_DIR=/var/lib/borg" | ||
94 | "BORG_CONFIG_DIR=/var/lib/borg/config" | ||
95 | "BORG_CACHE_DIR=/var/lib/borg/cache" | ||
96 | "BORG_SECURITY_DIR=/var/lib/borg/security" | ||
97 | "BORG_KEYS_DIR=/var/lib/borg/keys" | ||
98 | "BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes" | ||
99 | "BORG_HOSTNAME_IS_UNIQUE=yes" | ||
100 | ] ++ optional (!(isNull cfg.sshConfig)) "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${pkgs.writeText "config" cfg.sshConfig}\"" | ||
101 | ++ optional (!(isNull cfg.keyfile)) "BORG_KEY_FILE=${cfg.keyfile}"; | ||
102 | RuntimeDirectory = "zfssnap-prune"; | ||
103 | }; | ||
104 | }; | ||
105 | }; | ||
106 | } | ||
diff --git a/modules/zfssnap/default.nix b/modules/zfssnap/default.nix index f46cd510..f6f32852 100644 --- a/modules/zfssnap/default.nix +++ b/modules/zfssnap/default.nix | |||
@@ -48,6 +48,20 @@ in { | |||
48 | type = types.str; | 48 | type = types.str; |
49 | default = "*-*-* *:00/5:00"; | 49 | default = "*-*-* *:00/5:00"; |
50 | }; | 50 | }; |
51 | |||
52 | verbosity = mkOption { | ||
53 | type = types.int; | ||
54 | default = 2; | ||
55 | }; | ||
56 | |||
57 | extraPruneArgs = mkOption { | ||
58 | type = with types; listOf str; | ||
59 | default = []; | ||
60 | }; | ||
61 | extraAutosnapArgs = mkOption { | ||
62 | type = with types; listOf str; | ||
63 | default = []; | ||
64 | }; | ||
51 | }; | 65 | }; |
52 | }; | 66 | }; |
53 | 67 | ||
@@ -59,7 +73,7 @@ in { | |||
59 | before = [ "zfssnap-prune.service" ]; | 73 | before = [ "zfssnap-prune.service" ]; |
60 | serviceConfig = { | 74 | serviceConfig = { |
61 | Type = "oneshot"; | 75 | Type = "oneshot"; |
62 | ExecStart = "${zfssnap}/bin/zfssnap -vv"; | 76 | ExecStart = "${zfssnap}/bin/zfssnap --verbosity=${toString cfg.verbosity} autosnap ${escapeShellArgs cfg.extraAutosnapArgs}"; |
63 | 77 | ||
64 | LogRateLimitIntervalSec = 0; | 78 | LogRateLimitIntervalSec = 0; |
65 | }; | 79 | }; |
@@ -72,7 +86,7 @@ in { | |||
72 | ExecStart = let | 86 | ExecStart = let |
73 | mkSectionName = name: strings.escape [ "[" "]" ] (strings.toUpper name); | 87 | mkSectionName = name: strings.escape [ "[" "]" ] (strings.toUpper name); |
74 | zfssnapConfig = generators.toINI { inherit mkSectionName; } cfg.config; | 88 | zfssnapConfig = generators.toINI { inherit mkSectionName; } cfg.config; |
75 | in "${zfssnap}/bin/zfssnap -vv prune --config=${pkgs.writeText "zfssnap.ini" zfssnapConfig}"; | 89 | in "${zfssnap}/bin/zfssnap --verbosity=${toString cfg.verbosity} prune --config=${pkgs.writeText "zfssnap.ini" zfssnapConfig} ${escapeShellArgs cfg.extraPruneArgs}"; |
76 | 90 | ||
77 | LogRateLimitIntervalSec = 0; | 91 | LogRateLimitIntervalSec = 0; |
78 | }; | 92 | }; |
diff --git a/modules/zfssnap/zfssnap/zfssnap/__main__.py b/modules/zfssnap/zfssnap/zfssnap/__main__.py index 9d07401b..59478c71 100644 --- a/modules/zfssnap/zfssnap/zfssnap/__main__.py +++ b/modules/zfssnap/zfssnap/zfssnap/__main__.py | |||
@@ -375,10 +375,13 @@ def main(): | |||
375 | sys.excepthook = log_exceptions | 375 | sys.excepthook = log_exceptions |
376 | 376 | ||
377 | parser = argparse.ArgumentParser(prog='zfssnap') | 377 | parser = argparse.ArgumentParser(prog='zfssnap') |
378 | parser.add_argument('--verbosity', dest='log_level', action='append') | ||
378 | parser.add_argument('--verbose', '-v', dest='log_level', action='append_const', const=-1) | 379 | parser.add_argument('--verbose', '-v', dest='log_level', action='append_const', const=-1) |
379 | parser.add_argument('--quiet', '-q', dest='log_level', action='append_const', const=1) | 380 | parser.add_argument('--quiet', '-q', dest='log_level', action='append_const', const=1) |
380 | subparsers = parser.add_subparsers() | 381 | subparsers = parser.add_subparsers() |
381 | parser.set_defaults(cmd=autosnap) | 382 | parser.set_defaults(cmd=autosnap) |
383 | autosnap_parser = subparsers.add_parser('autosnap') | ||
384 | autosnap_parser.set_defaults(cmd=autosnap) | ||
382 | rename_parser = subparsers.add_parser('rename') | 385 | rename_parser = subparsers.add_parser('rename') |
383 | rename_parser.add_argument('snapshots', nargs='+') | 386 | rename_parser.add_argument('snapshots', nargs='+') |
384 | rename_parser.add_argument('--destroy', action='store_true', default=False) | 387 | rename_parser.add_argument('--destroy', action='store_true', default=False) |