default.nix (3330B) - Raw
1 { 2 config, 3 pkgs, 4 lib, 5 ... 6 }: 7 let 8 cfg = config.mj.services.btrfsborg; 9 in 10 { 11 options.mj.services.btrfsborg = with lib.types; { 12 enable = lib.mkEnableOption "backup btrfs snapshots with borg"; 13 14 passwordPath = lib.mkOption { type = str; }; 15 sshKeyPath = lib.mkOption { 16 type = nullOr path; 17 default = null; 18 }; 19 20 dirs = lib.mkOption { 21 default = { }; 22 type = listOf (submodule { 23 options = { 24 subvolume = lib.mkOption { type = path; }; 25 repo = lib.mkOption { type = str; }; 26 paths = lib.mkOption { type = listOf str; }; 27 patterns = lib.mkOption { 28 type = listOf str; 29 default = [ ]; 30 }; 31 prune = lib.mkOption { 32 type = anything; 33 default = { }; 34 }; 35 backup_at = lib.mkOption { type = str; }; 36 compression = lib.mkOption { 37 type = str; 38 default = "auto,zstd,10"; 39 }; 40 }; 41 }); 42 }; 43 }; 44 45 config = lib.mkIf cfg.enable { 46 systemd.services = lib.listToAttrs ( 47 lib.imap0 ( 48 i: attr: 49 let 50 svcName = "borgbackup-job-${lib.strings.sanitizeDerivationName attr.subvolume}-${toString i}"; 51 in 52 lib.nameValuePair svcName { serviceConfig.RuntimeDirectory = svcName; } 53 ) cfg.dirs 54 ); 55 56 services.borgbackup.jobs = builtins.listToAttrs ( 57 lib.imap0 ( 58 i: attrs: 59 let 60 subvolume = builtins.getAttr "subvolume" attrs; 61 in 62 assert lib.assertMsg config.mj.base.unitstatus.enable 63 "config.mj.base.unitstatus.enable must be true"; 64 lib.nameValuePair "${lib.strings.sanitizeDerivationName subvolume}-${toString i}" ( 65 { 66 inherit (attrs) repo paths compression; 67 68 doInit = true; 69 encryption = { 70 mode = "repokey-blake2"; 71 passCommand = "cat ${cfg.passwordPath}"; 72 }; 73 extraArgs = "--remote-path=borg1"; 74 extraCreateArgs = "--chunker-params buzhash,10,23,16,4095"; 75 startAt = attrs.backup_at; 76 preHook = '' 77 set -x 78 sleep ${toString i} 79 SNAPSHOT=$(${pkgs.btrfs-progs}/bin/btrfs subvolume list --sort=-gen -r -o ${subvolume} | \ 80 ${pkgs.gawk}/bin/awk '{print $9; exit}') 81 cd "/$SNAPSHOT" 82 ''; 83 prune.keep = { 84 within = "1d"; 85 daily = 7; 86 weekly = 4; 87 }; 88 environment = { 89 BORG_RELOCATED_REPO_ACCESS_IS_OK = "yes"; 90 BORG_HOST_ID = 91 let 92 h = config.networking; 93 in 94 "${h.hostName}.${h.domain}@${h.hostId}"; 95 } 96 // lib.optionalAttrs (cfg.sshKeyPath != null) { BORG_RSH = ''ssh -i "${cfg.sshKeyPath}"''; }; 97 } 98 // lib.optionalAttrs (attrs ? patterns) { inherit (attrs) patterns; } 99 // lib.optionalAttrs (attrs ? prune) { inherit (attrs) prune; } 100 ) 101 ) cfg.dirs 102 ); 103 104 mj.base.unitstatus.units = 105 let 106 sanitized = map lib.strings.sanitizeDerivationName (lib.catAttrs "subvolume" cfg.dirs); 107 in 108 lib.imap0 (i: name: "borgbackup-job-${name}-${toString i}") sanitized; 109 }; 110 }