config/modules/services/btrfsborg/default.nix

108 lines
3.2 KiB
Nix

{
config,
pkgs,
lib,
...
}:
let
cfg = config.mj.services.btrfsborg;
in
{
options.mj.services.btrfsborg = with lib.types; {
enable = lib.mkEnableOption "backup zfs snapshots with borg";
passwordPath = lib.mkOption { type = str; };
sshKeyPath = lib.mkOption {
type = nullOr path;
default = null;
};
dirs = lib.mkOption {
default = { };
type = listOf (submodule {
options = {
subvolume = lib.mkOption { type = path; };
repo = lib.mkOption { type = str; };
paths = lib.mkOption { type = listOf str; };
patterns = lib.mkOption {
type = listOf str;
default = [ ];
};
prune = lib.mkOption {
type = anything;
default = { };
};
backup_at = lib.mkOption { type = str; };
};
});
};
};
config = lib.mkIf cfg.enable {
systemd.services = lib.listToAttrs (
lib.imap0 (
i: attr:
let
svcName = "borgbackup-job-${lib.strings.sanitizeDerivationName attr.subvolume}-${toString i}";
in
lib.nameValuePair svcName { serviceConfig.RuntimeDirectory = svcName; }
) cfg.dirs
);
services.borgbackup.jobs = builtins.listToAttrs (
lib.imap0 (
i: attrs:
let
subvolume = builtins.getAttr "subvolume" attrs;
in
assert lib.assertMsg config.mj.base.unitstatus.enable
"config.mj.base.unitstatus.enable must be true";
lib.nameValuePair "${lib.strings.sanitizeDerivationName subvolume}-${toString i}" (
{
inherit (attrs) repo paths;
doInit = true;
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${cfg.passwordPath}";
};
extraArgs = "--remote-path=borg1";
compression = "auto,zstd,10";
extraCreateArgs = "--chunker-params buzhash,10,23,16,4095";
startAt = attrs.backup_at;
preHook = ''
set -x
sleep ${toString i}
SNAPSHOT=$(${pkgs.btrfs-progs}/bin/btrfs subvolume list --sort=-gen -r -o ${subvolume} | \
${pkgs.gawk}/bin/awk '{print $9; exit}')
cd "/$SNAPSHOT"
'';
prune.keep = {
within = "1d";
daily = 7;
weekly = 4;
monthly = 3;
};
environment = {
BORG_RELOCATED_REPO_ACCESS_IS_OK = "yes";
BORG_HOST_ID =
let
h = config.networking;
in
"${h.hostName}.${h.domain}@${h.hostId}";
} // lib.optionalAttrs (cfg.sshKeyPath != null) { BORG_RSH = ''ssh -i "${cfg.sshKeyPath}"''; };
}
// lib.optionalAttrs (attrs ? patterns) { inherit (attrs) patterns; }
// lib.optionalAttrs (attrs ? prune) { inherit (attrs) prune; }
)
) cfg.dirs
);
mj.base.unitstatus.units =
let
sanitized = map lib.strings.sanitizeDerivationName (lib.catAttrs "subvolume" cfg.dirs);
in
lib.imap0 (i: name: "borgbackup-job-${name}-${toString i}") sanitized;
};
}