summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hosts/sif/default.nix24
-rw-r--r--hosts/vidhar/borg.nix12
-rw-r--r--hosts/vidhar/borg/authorized-keys/surtr26
-rw-r--r--hosts/vidhar/borg/authorized-keys/surtr.pub1
-rw-r--r--hosts/vidhar/borg/authorized-keys/ymir21
-rw-r--r--hosts/vidhar/borg/authorized-keys/ymir.pub1
-rw-r--r--hosts/vidhar/borg/default.nix36
-rw-r--r--hosts/vidhar/borg/passphrase.yaml34
-rw-r--r--hosts/vidhar/default.nix2
-rw-r--r--modules/borgbackup/btrfs-snapshots.nix52
-rw-r--r--modules/borgbackup/default.nix206
-rw-r--r--modules/borgbackup/lvm-snapshots.nix133
-rw-r--r--modules/borgbackup/repokeys/borg_munin__borg.yaml33
13 files changed, 120 insertions, 461 deletions
diff --git a/hosts/sif/default.nix b/hosts/sif/default.nix
index 07ba564d..9516ceba 100644
--- a/hosts/sif/default.nix
+++ b/hosts/sif/default.nix
@@ -405,30 +405,6 @@ in {
405 ACTION=="add", SUBSYSTEM=="net", KERNEL=="virbr0", ENV{NM_UNMANAGED}="1" 405 ACTION=="add", SUBSYSTEM=="net", KERNEL=="virbr0", ENV{NM_UNMANAGED}="1"
406 ''; 406 '';
407 407
408 services.borgbackup = {
409 snapshots = "btrfs";
410 prefix = "yggdrasil.midgard.sif.";
411 targets = {
412 "munin" = {
413 repo = "borg.munin:borg";
414 paths = [ "/home/gkleen" ];
415 prune = {
416 "home" =
417 [ "--keep-within" "24H"
418 "--keep-daily" "31"
419 "--keep-monthly" "12"
420 "--keep-yearly" "-1"
421 ];
422 };
423 keyFile = "/run/secrets/borg-repokey--borg_munin__borg";
424 };
425 };
426 };
427 sops.secrets.borg-repokey--borg_munin__borg = {
428 sopsFile = /. + path + "/modules/borgbackup/repokeys/borg_munin__borg.yaml";
429 key = "key";
430 };
431
432 services.btrfs.autoScrub = { 408 services.btrfs.autoScrub = {
433 enable = true; 409 enable = true;
434 fileSystems = [ "/" "/home" ]; 410 fileSystems = [ "/" "/home" ];
diff --git a/hosts/vidhar/borg.nix b/hosts/vidhar/borg.nix
deleted file mode 100644
index 0a0b37a5..00000000
--- a/hosts/vidhar/borg.nix
+++ /dev/null
@@ -1,12 +0,0 @@
1{ ... }:
2{
3 config = {
4 users.users.borg = {
5 isSystemUser = true;
6 createHome = false;
7 group = "borg";
8 extraGroups = [ "ssh" ];
9 };
10 users.groups."borg" = {};
11 };
12}
diff --git a/hosts/vidhar/borg/authorized-keys/surtr b/hosts/vidhar/borg/authorized-keys/surtr
new file mode 100644
index 00000000..26d286b4
--- /dev/null
+++ b/hosts/vidhar/borg/authorized-keys/surtr
@@ -0,0 +1,26 @@
1{
2 "data": "ENC[AES256_GCM,data:UFWmVs/D1MtAW9ql+e9S5XRPBEmW5k09zCw+ftP8UgXPWSnNrutRpncsyvM07yqZw8qr4bhEErOrkmMk+BGcVlxGg55S7f6iJsj8GCFMhfJ5gVEa9jJRmEX8F9NZ2wlj3aeMni2JjBNnbypCwD7ffudK+sLNlhmVVwdNFCws2JQLnFW7mQOo/d8+BlPOxCebJIvmTq4K/b7+RqVuuqiK9t28Qt/eo0+F9aciXKyKZVM0bxw54Hh6yADqZ6ZTIzWbHb9+TL3HhP6dquNDqe2iiWaPzI5J63agpNDJ7uEtwTDW/irsIl3Ob5ekrXJ1FOaTmIUqRdyxty71ir6Aa/+JQIeVoC80oUgu1ImD9xenYD2v0EX4s6yJJV3a9bla3D3HRvZSfSuShbjfJDkegehXzFK0pVt2oAZMKKLHF25cx3In428evW7vb0R2aakf/tF0Gjlbooc+zEc2UgEp/YjYW5WaelWIK4ItwfmBRNYG9G5ZE0GT2I8UtHOiMQRA78ShxN7i,iv:H+YVF7wiUATbwnwzqO/LEZgWagnbeRRdMS9aK09vCbg=,tag:sDbC2g2xtjifS8Px3YI6vA==,type:str]",
3 "sops": {
4 "kms": null,
5 "gcp_kms": null,
6 "azure_kv": null,
7 "hc_vault": null,
8 "age": null,
9 "lastmodified": "2022-02-06T19:43:25Z",
10 "mac": "ENC[AES256_GCM,data:K3Y96+TM4/Jsl8JQ56tpJNHmkDVuetUtQbUpDqIHbqm65d+RKoL/Qy/IWVGqcfUxZMUvzM2J3fEo/05q8mcxn+wZd2tECSJEUbgFDhGrpPZV8Ir8cQCYlPn+UBTS4rNUfEpSBlymND/vFjQ0lneqMo5lapbetSs4h/GvFzUFw8M=,iv:TyzMk7wKzZpq8TrE9uHRFXi+JzvNePcWrmyogcoCZo0=,tag:KB6ZBlGrBSGuQFg4fB407w==,type:str]",
11 "pgp": [
12 {
13 "created_at": "2022-02-06T19:43:24Z",
14 "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DyFKFNkTVG5oSAQdAWSCnyt9/7PkWecNhcOwuw0TRJMld9dmV0Ti6KjR6bkAw\nQxTdj0rMaXFayEyyXxotbjxb/ZMTesYCqAce7RKoj0GS2GngmP6Xzpt151uSmyPs\n0l4Bh5Ohfln3bAq6iJvJfOZvwYqmoIicRZFFY7afuBDO7oad4fkoWpQWDRtuLc9M\nIC0ReFXCuQOI5eoFF3V8xT+X+icjFUCVC2OktO/6AlAtXxi6BSL+574CUMivuQz0\n=3v/M\n-----END PGP MESSAGE-----\n",
15 "fp": "7ED22F4AA7BB55728B643DC5471B7D88E4EF66F8"
16 },
17 {
18 "created_at": "2022-02-06T19:43:24Z",
19 "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdAqlj4zYxkXgnJEEt/RfxQORgOzyfiZdQKzlhm78OhsBkw\nc2EdfAgpGwIm1F8tpVtwYcfNXYgfaJdADMzYSHL8qqn8DJrvhCArJdT/m7ZPWKy2\n0l4B1hpQdga7KQTD/iDlIrTJtiZ9/AMtUJM/HU9KtCl9AFGRNEGTAEdlHTUBDzOP\nTSF+R4NAqoY742C7Lf7pkHbVhhpXige37qJhvu7AMgnT5TT17McsXUj52Sy+Qv3z\n=cBYd\n-----END PGP MESSAGE-----\n",
20 "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51"
21 }
22 ],
23 "unencrypted_suffix": "_unencrypted",
24 "version": "3.7.1"
25 }
26} \ No newline at end of file
diff --git a/hosts/vidhar/borg/authorized-keys/surtr.pub b/hosts/vidhar/borg/authorized-keys/surtr.pub
new file mode 100644
index 00000000..5c044d7a
--- /dev/null
+++ b/hosts/vidhar/borg/authorized-keys/surtr.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG5rfNezLOoI4ijzNNg61OGFfq4AXHlzVT0z/+RO0/ju surtr
diff --git a/hosts/vidhar/borg/authorized-keys/ymir b/hosts/vidhar/borg/authorized-keys/ymir
new file mode 100644
index 00000000..f3dd360c
--- /dev/null
+++ b/hosts/vidhar/borg/authorized-keys/ymir
@@ -0,0 +1,21 @@
1{
2 "data": "ENC[AES256_GCM,data:uzfOHmr0fct77EW5F/b5mSlckywoAKp/LCSZYTtUKa6HzbYujCUhlwqwFcc1lOQxfiDyQuJmhZaFbMgTSHyzf5zAfirQnCFPoUJFQf62TkQIoRNkTIYlzyzsaGl5uMZukl3r+qmd92Xoaf/d300Oq9P2k1RHQw2+UtyNn5B2OHD9hR9X6yXr8lRH8ABLKSFcqS2KrJXzYofoHub/V8OSldSRKpG3yy/CpsbVTOkc+ygBaH7orR6PWIy/iSummSGN6EaXdv2GZcqqf/h3iP8+xZlgqWnxRt0X5se6hrXNM0oU04fcs0sneqxUAQTvcnT75uO4z/lZ8ZTKDi05hCDzOF2iKybGjuJTGBMdAitQVC3DG7dtjbtnQ2xWrkZjkIRAGSz9Ud6rXmP0OILWYIhBHXgruyCJVJkTSBlu2Kcc+gwgEMfUHBq5k6rW13f1hlqikINDT6rkKH8IJyvMF0WTNdW0KVEemImKqfJccsfdPK6EdQDLOApq1vjd2djQVnIrCccV,iv:0qExktFJCrwkPbDzyUn2mWrHXCJsDPyZ0w2pSYl/bu8=,tag:N6RWe6owTuohMpyJoJaEjQ==,type:str]",
3 "sops": {
4 "kms": null,
5 "gcp_kms": null,
6 "azure_kv": null,
7 "hc_vault": null,
8 "age": null,
9 "lastmodified": "2022-02-06T20:15:30Z",
10 "mac": "ENC[AES256_GCM,data:uuScAvmls3hQFnuzG2KJXPEC2crHmkAlQGhIsxJRKCfsrlIyLZbDhNmB+MkYSJza4X4Cshm95DcFh7+A1QFa9VlZl+7iFx2RT23dMpW4aDGPB9w/SPUTFoUiKUkxsGIl0VemnoT3EuU3iPRGqGX859MGHAFe6XprCRKUnpU0OyA=,iv:pbG7dQ2ZEVMWmlx9AQfIJBs5Wu2pKCfYQ3DrzteJj28=,tag:UvDuRPJUU7ScgwrmbGjPiA==,type:str]",
11 "pgp": [
12 {
13 "created_at": "2022-02-06T20:15:29Z",
14 "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdAAju8aRDlzlNFdCuiVeg7Kak6DgixY2Gq5fRqS78PP3Mw\nRZyzG8ZaNBSHIG+lZtgdYcMEe1kH83KZ7pimlh3jKCumpdyB0jEdoMl1VLYhaaw9\n0l4B8yQ4DbxuJuTrrlI4XtMO4srMQXn88UlqDb33ScURLPhl2Xmlhn9JNEoOgut9\nr+vQ5jj1/Cf7jE9fLeB9JcPyKeJJftIM4TBn+trvC/RaKs4gq1UVRH15WFTNRG5/\n=ncoV\n-----END PGP MESSAGE-----\n",
15 "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51"
16 }
17 ],
18 "unencrypted_suffix": "_unencrypted",
19 "version": "3.7.1"
20 }
21} \ No newline at end of file
diff --git a/hosts/vidhar/borg/authorized-keys/ymir.pub b/hosts/vidhar/borg/authorized-keys/ymir.pub
new file mode 100644
index 00000000..a62fcfdf
--- /dev/null
+++ b/hosts/vidhar/borg/authorized-keys/ymir.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGRPw65gJccLR1bdKeyD/GB6dBBXPffP0JM9FvvIATzS ymir
diff --git a/hosts/vidhar/borg/default.nix b/hosts/vidhar/borg/default.nix
new file mode 100644
index 00000000..d338dfd6
--- /dev/null
+++ b/hosts/vidhar/borg/default.nix
@@ -0,0 +1,36 @@
1{ pkgs, lib, ... }:
2
3with lib;
4
5{
6 config = {
7 services.borgbackup.repos.borg = {
8 path = "/srv/backup/borg";
9 authorizedKeysAppendOnly = let
10 dir = ./authorized-keys;
11 toAuthKey = fname: ftype: if ftype != "regular" || !(hasSuffix ".pub" fname) then null else builtins.readFile (dir + "/${fname}");
12 in filter (v: v != null) (lib.mapAttrsToList toAuthKey (builtins.readDir dir));
13 };
14
15 boot.postBootCommands = mkBefore ''
16 ${pkgs.findutils}/bin/find /srv/backup/borg -maxdepth 1 -type d -empty -delete
17 '';
18
19 services.openssh.extraConfig = ''
20 Match User borg
21 ClientAliveInterval 10
22 ClientAliveCountMax 30
23
24 Match All
25 '';
26
27 sops.secrets.borg-passphrase = {
28 sopsFile = ./passphrase.yaml;
29 format = "yaml";
30 key = "borg";
31 owner = "borg";
32 group = "borg";
33 mode = "0440";
34 };
35 };
36}
diff --git a/hosts/vidhar/borg/passphrase.yaml b/hosts/vidhar/borg/passphrase.yaml
new file mode 100644
index 00000000..6a306cea
--- /dev/null
+++ b/hosts/vidhar/borg/passphrase.yaml
@@ -0,0 +1,34 @@
1borg: ENC[AES256_GCM,data:Ly3WfFtHqQAK7E3MwSPMMOfVshwPurMLtAMYdfStlOk=,iv:taLOAWrdD8AkrPdMjxq3fdvIzyGAtU0NBGhdm6DKRO8=,tag:o84PE6fiVFT/NVp5HanZrg==,type:str]
2sops:
3 kms: []
4 gcp_kms: []
5 azure_kv: []
6 hc_vault: []
7 age: []
8 lastmodified: "2022-02-06T20:18:06Z"
9 mac: ENC[AES256_GCM,data:Se6Sft5FgW9SYw2PRzDCO/v0BXQSLgRSHh9UGMUCI3sfoZ00D5a3GGgNB7JN0D598ztGmShWUJi03JzxxYOOhIaJZB/Fk5cUUOsEx4kQErXCBrlktowZz7grq3E04tNzKQqzUJ83g3W/4/N6YrAKUnu/mWtMOwnxEithdTtrpS4=,iv:XVmFDCqm3Oa4/gZRVI3XWHyQ0GQE0II7OKWGDGn5TXI=,tag:e2L/dmYlpoGZb4cXClQ0vg==,type:str]
10 pgp:
11 - created_at: "2022-02-06T20:16:31Z"
12 enc: |
13 -----BEGIN PGP MESSAGE-----
14
15 hF4DyFKFNkTVG5oSAQdAShFePaI/3pObNwFOa51ZPydA89cfwnErU9zE1/A68Qow
16 knL5rHbFSUUqGkiKT7syl1G9BupEAHz4BrFEXzc11VE5qc5vF3W6Lm9Agp3W/21W
17 0l4BAmm/sqUKSCCqRiSQmVVlpl5Hs7tOMwUsBpZb53edik4oBd7hzsI4y9n0viEa
18 FhAkXtGI0LzpFRosrbHt1jTK+u9360BO4959AMIfcUCYmIYKscs47Ux3EDzk6+2i
19 =Azsm
20 -----END PGP MESSAGE-----
21 fp: 7ED22F4AA7BB55728B643DC5471B7D88E4EF66F8
22 - created_at: "2022-02-06T20:16:31Z"
23 enc: |
24 -----BEGIN PGP MESSAGE-----
25
26 hF4DXxoViZlp6dISAQdAIlHLZ6ipYghBjZeqfGv/VSsqsJHU3c6589TiSxXmCV8w
27 gScJtpO/R3DX1zUAVxxkOoGnJ0qS9IhBEOB4D/ET+vPteR5IIx26a3TFp4vlMXRc
28 0l4BSikg39kSaxp+URvRJyAT1VQIprVkuEEmvgM5klvB+gitU0BhW//cEBvhW7SE
29 v+lfGy9PrpCb5yWpCN1H3DyfGwcRl6Qp3gkH5rs+/vpg39fs/Hh0CG+YnlHMzZ39
30 =I8PE
31 -----END PGP MESSAGE-----
32 fp: 30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51
33 unencrypted_suffix: _unencrypted
34 version: 3.7.1
diff --git a/hosts/vidhar/default.nix b/hosts/vidhar/default.nix
index 09ae1e1e..c2d3461b 100644
--- a/hosts/vidhar/default.nix
+++ b/hosts/vidhar/default.nix
@@ -1,7 +1,7 @@
1{ hostName, flake, config, pkgs, lib, ... }: 1{ hostName, flake, config, pkgs, lib, ... }:
2{ 2{
3 imports = with flake.nixosModules.systemProfiles; [ 3 imports = with flake.nixosModules.systemProfiles; [
4 ./zfs.nix ./network ./samba.nix ./dns.nix ./prometheus ./borg.nix 4 ./zfs.nix ./network ./samba.nix ./dns.nix ./prometheus ./borg
5 initrd-all-crypto-modules default-locale openssh rebuild-machines 5 initrd-all-crypto-modules default-locale openssh rebuild-machines
6 build-server 6 build-server
7 initrd-ssh 7 initrd-ssh
diff --git a/modules/borgbackup/btrfs-snapshots.nix b/modules/borgbackup/btrfs-snapshots.nix
deleted file mode 100644
index 96d2b2ba..00000000
--- a/modules/borgbackup/btrfs-snapshots.nix
+++ /dev/null
@@ -1,52 +0,0 @@
1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.btrfs-snapshots;
7
8 snapshotMount = str: "${str}${cfg.mountSuffix}";
9in {
10 options = {
11
12 services.btrfs-snapshots = {
13 enable = mkEnableOption "a systemd unit for btrfs snapshots";
14
15 mountSuffix = mkOption {
16 type = types.str;
17 default = ".snapshot";
18 };
19
20 readOnly = mkOption {
21 type = types.bool;
22 default = true;
23 };
24
25 persist = mkOption {
26 type = types.bool;
27 default = false;
28 };
29 };
30
31 };
32
33
34 config = mkIf cfg.enable {
35 systemd.services."btrfs-snapshot@" = {
36 enable = true;
37
38 unitConfig = {
39 StopWhenUnneeded = !cfg.persist;
40 };
41
42 serviceConfig = with pkgs; {
43 Type = "oneshot";
44 ExecStartPre = "-${btrfs-progs}/bin/btrfs subvolume delete -c ${snapshotMount "%f"}";
45 ExecStart = "${btrfs-progs}/bin/btrfs subvolume snapshot ${optionalString cfg.readOnly "-r"} %f ${snapshotMount "%f"}";
46 RemainAfterExit = true;
47 ExecStop = "${btrfs-progs}/bin/btrfs subvolume delete -c ${snapshotMount "%f"}";
48 };
49 };
50
51 };
52}
diff --git a/modules/borgbackup/default.nix b/modules/borgbackup/default.nix
deleted file mode 100644
index a0419d0e..00000000
--- a/modules/borgbackup/default.nix
+++ /dev/null
@@ -1,206 +0,0 @@
1{ config, lib, utils, pkgs, ... }:
2
3with utils;
4with lib;
5
6let
7 cfg = config.services.borgbackup;
8
9 lvmPath = {
10 options = {
11 LV = mkOption {
12 type = types.str;
13 };
14 VG = mkOption {
15 type = types.str;
16 };
17 };
18 };
19
20 pathType = if cfg.snapshots == "lvm" then types.submodule lvmPath else types.path;
21
22 systemdPath = path: escapeSystemdPath (if cfg.snapshots == "lvm" then "${path.VG}-${path.LV}" else path);
23
24 withSuffix = path: path + (if cfg.snapshots == "btrfs" then config.services.btrfs-snapshots.mountSuffix else config.services.lvm-snapshots.mountSuffix);
25
26 mountPoint = if cfg.snapshots == "lvm" then config.services.lvm-snapshots.mountPoint else "";
27
28 targetOptions = {
29 options = {
30 repo = mkOption {
31 type = types.str;
32 };
33
34 paths = mkOption {
35 type = types.listOf pathType;
36 default = [];
37 };
38
39 prune = mkOption {
40 type = types.attrsOf (types.listOf types.str);
41 default = {};
42 };
43
44 interval = mkOption {
45 type = types.str;
46 default = "6h";
47 };
48
49 jitter = mkOption {
50 type = with types; nullOr str;
51 default = "6h";
52 };
53
54 lock = mkOption {
55 type = types.nullOr types.str;
56 default = "backup";
57 };
58
59 network = mkOption {
60 type = types.bool;
61 default = true;
62 };
63
64 lockWait = mkOption {
65 type = types.int;
66 default = 600;
67 };
68
69 keyFile = mkOption {
70 type = types.nullOr types.path;
71 default = null;
72 };
73 };
74 };
75in {
76 disabledModules = [ "services/backup/borgbackup.nix" ];
77
78 options = {
79 services.borgbackup = {
80 snapshots = mkOption {
81 type = types.nullOr (types.enum ["btrfs" "lvm"]);
82 default = null;
83 };
84
85 targets = mkOption {
86 type = types.attrsOf (types.submodule targetOptions);
87 default = {};
88 };
89
90 prefix = mkOption {
91 type = types.str;
92 };
93 };
94 };
95
96 imports =
97 [ ./lvm-snapshots.nix
98 ./btrfs-snapshots.nix
99 ];
100
101 config = mkIf (any (t: t.paths != []) (attrValues cfg.targets)) {
102 services.btrfs-snapshots.enable = mkIf (cfg.snapshots == "btrfs") true;
103
104 services.lvm-snapshots.snapshots = mkIf (cfg.snapshots == "lvm") (listToAttrs (map (path: nameValuePair (path.VG + "-" + path.LV) {
105 inherit (path) LV VG;
106 mountName = withSuffix (path.VG + "-" + path.LV);
107 }) (unique (flatten (mapAttrsToList (target: tCfg: tCfg.paths) cfg.targets)))));
108
109 systemd.targets."timers-borg" = {
110 wantedBy = [ "timers.target" ];
111 };
112
113 systemd.slices."system-borgbackup" = {};
114
115 systemd.timers = (listToAttrs (map ({ target, path, tCfg }: nameValuePair "borgbackup-${target}@${systemdPath path}" {
116 requiredBy = [ "timers-borg.target" ];
117
118 timerConfig = {
119 Persistent = false;
120 OnBootSec = tCfg.interval;
121 OnUnitActiveSec = tCfg.interval;
122 RandomizedDelaySec = mkIf (tCfg.jitter != null) tCfg.jitter;
123 };
124 }) (flatten (mapAttrsToList (target: tCfg: map (path: { inherit target path tCfg; }) tCfg.paths) cfg.targets)))) // (mapAttrs' (target: tCfg: nameValuePair "borgbackup-prune-${target}" {
125 enable = tCfg.prune != {};
126
127 requiredBy = [ "timers-borg.target" ];
128
129 timerConfig = {
130 Persistent = false;
131 OnBootSec = tCfg.interval;
132 OnUnitActiveSec = tCfg.interval;
133 RandomizedDelaySec = mkIf (tCfg.jitter != null) tCfg.jitter;
134 };
135 }) cfg.targets);
136
137 systemd.services = (mapAttrs' (target: tCfg: nameValuePair "borgbackup-${target}@" (let
138 deps = flatten [
139 (optional (cfg.snapshots == "btrfs") "btrfs-snapshot@%i.service")
140 (optional tCfg.network "network-online.target")
141 ];
142 in {
143 bindsTo = deps;
144 after = deps;
145
146 path = with pkgs; [borgbackup] ++ optional (tCfg.lock != null) utillinux;
147
148 script = let
149 borgCmd = ''
150 borg create \
151 --lock-wait ${toString tCfg.lockWait} \
152 --stats \
153 --list \
154 --filter 'AME' \
155 --exclude-caches \
156 --keep-exclude-tags \
157 --patterns-from .backup-${target} \
158 --one-file-system \
159 --compression auto,lzma \
160 ${tCfg.repo}::${cfg.prefix}$1-{utcnow}
161 '';
162 in if tCfg.lock == null then borgCmd else "flock -xo /var/lock/${tCfg.lock} ${borgCmd}";
163 scriptArgs = if cfg.snapshots == "lvm" then "%I" else "%i";
164
165 unitConfig = {
166 AssertPathIsDirectory = mkIf (tCfg.lock != null) "/var/lock";
167 DefaultDependencies = false;
168 RequiresMountsFor = mkIf (cfg.snapshots == "lvm") [ "${mountPoint}/${withSuffix "%I"}" ];
169 };
170
171 serviceConfig = {
172 Type = "oneshot";
173 WorkingDirectory = if (cfg.snapshots == null) then "%I" else (if (cfg.snapshots == "lvm") then "${mountPoint}/${withSuffix "%I"}" else "${withSuffix "%f"}");
174 Nice = 15;
175 IOSchedulingClass = 2;
176 IOSchedulingPriority = 7;
177 SuccessExitStatus = [1 2];
178 Slice = "system-borgbackup.slice";
179 Environment = lib.mkIf (tCfg.keyFile != null) "BORG_KEY_FILE=${tCfg.keyFile}";
180 };
181 })) cfg.targets) // (mapAttrs' (target: tCfg: nameValuePair "borgbackup-prune-${target}" {
182 enable = tCfg.prune != {};
183
184 bindsTo = ["network-online.target"];
185 after = ["network-online.target"];
186
187 path = with pkgs; [borgbackup];
188
189 script = concatStringsSep "\n" (mapAttrsToList (path: args: ''
190 borg prune \
191 --lock-wait ${toString tCfg.lockWait} \
192 --list \
193 --stats \
194 --prefix ${escapeShellArg "${cfg.prefix}${path}"} \
195 ${escapeShellArgs args} \
196 ${tCfg.repo}
197 '') tCfg.prune);
198
199 serviceConfig = {
200 Type = "oneshot";
201 Slice = "system-borgbackup.slice";
202 Environment = lib.mkIf (tCfg.keyFile != null) "BORG_KEY_FILE=${tCfg.keyFile}";
203 };
204 }) cfg.targets);
205 };
206}
diff --git a/modules/borgbackup/lvm-snapshots.nix b/modules/borgbackup/lvm-snapshots.nix
deleted file mode 100644
index 9b2a6562..00000000
--- a/modules/borgbackup/lvm-snapshots.nix
+++ /dev/null
@@ -1,133 +0,0 @@
1{ config, lib, utils, pkgs, ... }:
2
3with utils;
4with lib;
5
6let
7 cfg = config.services.lvm-snapshots;
8
9 snapshotMount = name: "${cfg.mountPoint}/${if isNull cfg.snapshots."${name}".mountName then name else cfg.snapshots."${name}".mountName}";
10 snapshotName = name: "${name}-${cfg.mountSuffix}";
11
12 snapshotConfig = {
13 options = {
14 LV = mkOption {
15 type = types.str;
16 };
17
18 VG = mkOption {
19 type = types.str;
20 };
21
22 mountName = mkOption {
23 type = types.nullOr types.str;
24 default = null;
25 };
26
27 cowSize = mkOption {
28 type = types.str;
29 default = "-l20%ORIGIN";
30 };
31
32 readOnly = mkOption {
33 type = types.bool;
34 default = true;
35 };
36
37 persist = mkOption {
38 type = types.bool;
39 default = false;
40 };
41 };
42 };
43in {
44 options = {
45
46 services.lvm-snapshots = {
47 snapshots = mkOption {
48 type = types.attrsOf (types.submodule snapshotConfig);
49 default = {};
50 };
51
52 mountPoint = mkOption {
53 type = types.path;
54 default = "/mnt";
55 };
56
57 mountSuffix = mkOption {
58 type = types.str;
59 default = "-snapshot";
60 };
61 };
62 };
63
64
65 config = mkIf (cfg != {}) {
66
67 boot.kernelModules = [ "dm_snapshot" ];
68
69 # system.activationScripts = mapAttrs' (name: scfg: nameValuePair ("lvm-mountpoint" + name) ''
70 # mkdir -p ${snapshotMount name}
71 # '') cfg.snapshots;
72
73 systemd.services = mapAttrs' (name: scfg: nameValuePair ("lvm-snapshot@" + escapeSystemdPath name) {
74 enable = true;
75
76 description = "LVM-snapshot of ${scfg.VG}/${scfg.LV}";
77
78 bindsTo = ["${escapeSystemdPath "/dev/${scfg.VG}/${scfg.LV}"}.device"];
79 after = ["${escapeSystemdPath "/dev/${scfg.VG}/${scfg.LV}"}.device"];
80
81 unitConfig = {
82 StopWhenUnneeded = !scfg.persist;
83 AssertPathIsDirectory = "/var/lock";
84 };
85
86 path = with pkgs; [ devicemapper utillinux ];
87
88 script = ''
89 (
90 flock -xn -E 4 9
91 if [[ "$?" -ne 0 ]]; then
92 exit $?
93 fi
94
95 lvcreate -s ${scfg.cowSize} --name ${snapshotName name} ${scfg.VG}/${scfg.LV}
96
97 sleep infinity &
98 ) 9>/var/lock/lvm-snapshot.${scfg.VG}
99 '';
100
101 preStart = ''
102 lvremove -f ${scfg.VG}/${snapshotName name}
103 '';
104
105 preStop = ''
106 lvremove -f ${scfg.VG}/${snapshotName name}
107 '';
108
109 serviceConfig = with pkgs; {
110 Type = "forking";
111 RestartForceExitStatus = [ "4" ];
112 RestartSec = "5min";
113 };
114 }) cfg.snapshots;
115
116 systemd.mounts = mapAttrsToList (name: scfg: {
117 enable = true;
118
119 unitConfig = {
120 # AssertPathIsDirectory = snapshotMount name;
121 StopWhenUnneeded = !scfg.persist;
122 };
123
124 bindsTo = [ ("lvm-snapshot@" + escapeSystemdPath name + ".service") ];
125 after = [ ("lvm-snapshot@" + escapeSystemdPath name + ".service") ];
126
127 options = concatStringsSep "," ([ "noauto" ] ++ optional scfg.readOnly "ro");
128
129 where = snapshotMount name;
130 what = "/dev/" + scfg.VG + "/" + snapshotName name;
131 }) cfg.snapshots;
132 };
133}
diff --git a/modules/borgbackup/repokeys/borg_munin__borg.yaml b/modules/borgbackup/repokeys/borg_munin__borg.yaml
deleted file mode 100644
index f302fe06..00000000
--- a/modules/borgbackup/repokeys/borg_munin__borg.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
1key: ENC[AES256_GCM,data:mxh+Jtxx+HyD246yPwo0vy7vSTz3IG8VmfbxPMwqJRreh9ZwkGnH5aCTDOvWOHIrkmzaRMF3oCi1P8D29+abMUZdt0MuJ3UE6iL8+SXlflR+WACgALM2Df+x9B3BwQM3yeoCiWG+ebr0iQPHM3jqqpkjoRv1CcythxG2deZueur9lzgC2CwG1g3O8Prnl9z0JQGOa+gjic8Zwfn38B1BECeNPrbjzICGBOrSbN/6EnfBDygI2QzseamzK2I6R6jT+QxHvkl+Zi1m2TRB+4o82VgTjPhIReJyT7PrlDnUyrKObhCOlb3v+LiSdp16IPIDVs968kyDzgyi7QPOpGr+5tutWCZrau5xhPDrONKByl/0nVVwEZfRIYATvEXtn5okJru/mglcpeD0I7AtLt+Vfv9CB9pQczvkHo0cDtgudQDf9ADt/nkmqHugm5VfMg9m9aGbKqzXt6pPOMsXSbS43K7wgDaduLZ/PW4Ookx9gTNLtJHnZ64GBorOv4QSrZIZF8pE1FsQdUhmp/YzVhaNBnjCr+Jh77sYjoOwzF77Xy+VP2C/yVIf492P+FcgkSj6XhYYqHffpFW9l/xmUvyQF5gjj2k5T21UvgChhI1HeLPzQ7W9+xuGSMtg58aD/VPe1loCy8zLITNl71bneararRS5vItoZyzMdmIRMLAZD1klPmDNe1yufTpubOXzNYbWUqFUZtwH/mDL5GRZBD9dqs2b3F26c1CUyw==,iv:NJBHesKSZ1zuKk8qHnYKqIwMnFkH+rkQD1bam5XpLXU=,tag:EiYbIFY/r/eTSTJIhYV+GA==,type:str]
2sops:
3 kms: []
4 gcp_kms: []
5 azure_kv: []
6 hc_vault: []
7 lastmodified: '2021-01-02T20:38:48Z'
8 mac: ENC[AES256_GCM,data:3rkFTOk3r2dx3hOqu1u7XIIibTDfqNlRcWY9X2N/LFa/BKojgDt5tcpbphV4HqWvl8nS+fPcVrIElJfQ/QGFEOx68G95BhByntT9+JhSbHJt73dGnCSroZCw5QefdydREGvA5n00Vo9yT9IMvQsQbmpRzo6hcrSSUvagZqmZckA=,iv:F/HllDzyxgulIWZbfz9bFKR+SFg4PoaUYZ5N5hfIzw0=,tag:h2NXmvj/thhBg1rIkwdXXA==,type:str]
9 pgp:
10 - created_at: '2021-01-02T20:38:09Z'
11 enc: |
12 -----BEGIN PGP MESSAGE-----
13
14 hF4Dgwm4NZSaLAcSAQdAwmvyXlr9MyfPfLgkfQkoktKBV2WA2xhZrGL7NeeGfhAw
15 REk+clJ9WgiJ0iceRAONPnEjeiK0J6Fsj+5Ulq8flFGkoj5Pta0pm/9fudKmcPdC
16 0l4BF0G5LSpG1EmY+LmVdSdas16rWgthnojoXPvbbHG6jZs3aDETshdiN8Bdlqsf
17 aVhq2LYzscnYezNcdernR4uojtiFny8qcmdF3tFacr+mkgfgIQr0W9yWFhDH15gm
18 =4TwU
19 -----END PGP MESSAGE-----
20 fp: F1AF20B9511B63F681A14E8D51AEFBCD1DEF68F8
21 - created_at: '2021-01-02T20:38:09Z'
22 enc: |
23 -----BEGIN PGP MESSAGE-----
24
25 hF4DXxoViZlp6dISAQdAruPXj9IsllEN7R5jk4gF7bW0ZirhvX7qsu22/6HbSw8w
26 66RwN3WGjYO1CcVbHKuLqVVaUBCnrR/4XHN0JYUaqjubrSZBTWFKTBFsKSTT0LZq
27 0l4BKcsXrbGpYC5+yQvg0RHJ7LplxpKOmqMY8KGckvGnVf2xg7k6wuWQREFzqwt+
28 lOa3x+xFy9c0JwE8AafyKjb/cgqJiMb96lhsH57BpXJa2E39ImQbXqzDzdx2jEUt
29 =3rxi
30 -----END PGP MESSAGE-----
31 fp: 30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51
32 unencrypted_suffix: _unencrypted
33 version: 3.6.1