diff options
| -rw-r--r-- | hosts/sif/default.nix | 24 | ||||
| -rw-r--r-- | hosts/vidhar/borg.nix | 12 | ||||
| -rw-r--r-- | hosts/vidhar/borg/authorized-keys/surtr | 26 | ||||
| -rw-r--r-- | hosts/vidhar/borg/authorized-keys/surtr.pub | 1 | ||||
| -rw-r--r-- | hosts/vidhar/borg/authorized-keys/ymir | 21 | ||||
| -rw-r--r-- | hosts/vidhar/borg/authorized-keys/ymir.pub | 1 | ||||
| -rw-r--r-- | hosts/vidhar/borg/default.nix | 36 | ||||
| -rw-r--r-- | hosts/vidhar/borg/passphrase.yaml | 34 | ||||
| -rw-r--r-- | hosts/vidhar/default.nix | 2 | ||||
| -rw-r--r-- | modules/borgbackup/btrfs-snapshots.nix | 52 | ||||
| -rw-r--r-- | modules/borgbackup/default.nix | 206 | ||||
| -rw-r--r-- | modules/borgbackup/lvm-snapshots.nix | 133 | ||||
| -rw-r--r-- | modules/borgbackup/repokeys/borg_munin__borg.yaml | 33 |
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 | |||
| 3 | with 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 @@ | |||
| 1 | borg: ENC[AES256_GCM,data:Ly3WfFtHqQAK7E3MwSPMMOfVshwPurMLtAMYdfStlOk=,iv:taLOAWrdD8AkrPdMjxq3fdvIzyGAtU0NBGhdm6DKRO8=,tag:o84PE6fiVFT/NVp5HanZrg==,type:str] | ||
| 2 | sops: | ||
| 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 | |||
| 3 | with lib; | ||
| 4 | |||
| 5 | let | ||
| 6 | cfg = config.services.btrfs-snapshots; | ||
| 7 | |||
| 8 | snapshotMount = str: "${str}${cfg.mountSuffix}"; | ||
| 9 | in { | ||
| 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 | |||
| 3 | with utils; | ||
| 4 | with lib; | ||
| 5 | |||
| 6 | let | ||
| 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 | }; | ||
| 75 | in { | ||
| 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 | |||
| 3 | with utils; | ||
| 4 | with lib; | ||
| 5 | |||
| 6 | let | ||
| 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 | }; | ||
| 43 | in { | ||
| 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 @@ | |||
| 1 | key: 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] | ||
| 2 | sops: | ||
| 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 | ||
