diff --git a/flake.nix b/flake.nix index e317f4c..a9d63f4 100644 --- a/flake.nix +++ b/flake.nix @@ -102,6 +102,7 @@ } ./hosts/ytnix inputs.sops-nix.nixosModules.sops + ./modules ]; }; @@ -113,6 +114,7 @@ } ./hosts/chunk inputs.sops-nix.nixosModules.sops + ./modules ]; }; @@ -125,6 +127,7 @@ ./hosts/titan disko.nixosModules.disko inputs.sops-nix.nixosModules.sops + ./modules ]; }; }; diff --git a/hosts/chunk/borg.nix b/hosts/chunk/borg.nix index 9b07eca..b3a76b5 100644 --- a/hosts/chunk/borg.nix +++ b/hosts/chunk/borg.nix @@ -48,11 +48,11 @@ # warnings are often not that serious failOnWarnings = false; postHook = '' - ${pkgs.curl}/bin/curl -u $(cat ${ + ${pkgs.curl}/bin/curl -O /dev/null -u $(cat ${ config.sops.secrets."services/ntfy".path }) -d "chunk: backup completed with exit code: $exitStatus - $(journalctl -u borgbackup-job-crashRsync.service|tail -n 5)" \ - https://ntfy.cything.io/chunk + $(journalctl --output-fields=MESSAGE -o cat -qu borgbackup-job-crashRsync.service |tail -n 10) + " https://ntfy.cything.io/ytnix ''; prune.keep = { diff --git a/hosts/ytnix/default.nix b/hosts/ytnix/default.nix index 81dcc27..e8e2ee9 100644 --- a/hosts/ytnix/default.nix +++ b/hosts/ytnix/default.nix @@ -188,66 +188,20 @@ programs.sway.enable = true; - services.borgbackup.jobs.ytnixRsync = { - # systemd.timer(5) - persistentTimer = true; - paths = [ - "/root" - "/home" - "/var/lib" - "/opt" - "/etc" - ]; + my.backup= { + enable = true; + jobName = "ytnixRsync"; exclude = [ - "**/.cache" - "**/node_modules" - "**/cache" - "**/Cache" - "/var/lib/docker" "/var/lib/private/ollama" - "/var/lib/libvirt" - "/var/lib/systemd" "/home/**/Downloads" - "**/.rustup" - "**/.cargo" - "**/.docker" - "**/borg" "/home/yt/fun" "/home/yt/.local/share/Steam" "**/.wine" "/home/yt/Games" ]; - repo = "de3911@de3911.rsync.net:borg/yt"; - encryption = { - mode = "repokey-blake2"; - passCommand = ''cat ${config.sops.secrets."borg/rsyncnet".path}''; - }; - environment = { - BORG_RSH = ''ssh -i ${config.sops.secrets."rsyncnet/id_ed25519".path}''; - BORG_REMOTE_PATH = "borg1"; - BORG_EXIT_CODES = "modern"; - }; - compression = "auto,zstd,8"; - startAt = "hourly"; - extraCreateArgs = [ - "--stats" - "-x" - ]; - # warnings are often not that serious - failOnWarnings = false; - postHook = '' - ${pkgs.curl}/bin/curl -u $(cat ${ - config.sops.secrets."services/ntfy".path - }) -d "ytnixRsync: backup completed with exit code: $exitStatus - $(journalctl -u borgbackup-job-ytnixRsync.service|tail -n 5)" \ - https://ntfy.cything.io/chunk - ''; - - prune.keep = { - within = "2d"; - daily = 365; - }; - extraPruneArgs = [ "--stats" ]; + repo = "yt"; + passFile = config.sops.secrets."borg/rsyncnet".path; + sshKeyFile = config.sops.secrets."rsyncnet/id_ed25519".path; }; services.btrbk.instances.local = { diff --git a/modules/backup.nix b/modules/backup.nix new file mode 100644 index 0000000..e5c5e58 --- /dev/null +++ b/modules/backup.nix @@ -0,0 +1,112 @@ +{ config, lib, pkgs, ... }: let + cfg = config.my.backup; + hostname = config.networking.hostName; + defaultPaths = [ + "/root" + "/home" + "/var/lib" + "/opt" + "/etc" + "/var/backup" + ]; + defaultExclude = [ + "**/.cache" + "**/node_modules" + "**/cache" + "**/Cache" + "/var/lib/docker" + "/var/lib/systemd" + "/var/lib/libvirt" + "**/.rustup" + "**/.cargo" + "**/.docker" + "**/borg" + ]; +in { + options.my.backup = { + enable = lib.mkEnableOption "backup"; + paths = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Paths to backup. Appended to the list of defaultPaths"; + }; + exclude = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Paths to exclude. Appended to the list of defaultExclude"; + }; + repo = lib.mkOption { + type = lib.types.str; + description = "Borg repository to backup to. This is appended to `de3911@de3911.rsync.net:borg/`."; + }; + startAt = lib.mkOption { + type = lib.types.str; + default = "hourly"; + description = "see systemd.timer(5)"; + }; + jobName = lib.mkOption { + type = lib.types.str; + description = "Name of the job to run as. Archives created are prefixed with hostName-jobName"; + }; + passFile = lib.mkOption { + type = lib.types.str; + description = "Path to the file containing the encryption passphrase"; + }; + sshKeyFile = lib.mkOption { + type = lib.types.str; + description = "Path to the file containg the SSH identity key"; + }; + }; + + config = lib.mkIf cfg.enable { + programs.ssh.knownHostsFiles = [ + (pkgs.writeText "rsyncnet-keys" '' + de3911.rsync.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIObQN4P/deJ/k4P4kXh6a9K4Q89qdyywYetp9h3nwfPo + '') + ]; # needs to be a list + + services.borgbackup.jobs.${cfg.jobName} = { + inherit (cfg) startAt; + + # systemd.timer(5) + persistentTimer = true; + paths = defaultPaths ++ cfg.paths; + exclude = defaultExclude ++ cfg.exclude; + repo = "de3911@de3911.rsync.net:borg/" + cfg.repo; + encryption = { + mode = "repokey-blake2"; + passCommand = "cat ${cfg.passFile}"; + }; + environment = { + BORG_RSH = "ssh -i ${cfg.sshKeyFile}"; + BORG_REMOTE_PATH = "borg1"; + BORG_EXIT_CODES = "modern"; + }; + compression = "auto,zstd,8"; + extraCreateArgs = [ + "--stats" + "-x" + ]; + # warnings are often not that serious + failOnWarnings = false; + postHook = '' + invocationId=$(systemctl show -p InvocationID --value borgbackup-job-${cfg.jobName}.service) + title="${hostname}: backup completed with exit code: $exitStatus" + msg=$(journalctl -o cat _SYSTEMD_INVOCATION_ID=$invocationId) + + ${pkgs.curl}/bin/curl -sL -u $(cat ${ + config.sops.secrets."services/ntfy".path + }) \ + -H "Title: $title" \ + -d "$msg" \ + https://ntfy.cything.io/backups > /dev/null + ''; + + prune.keep = { + within = "2d"; + daily = 365; + }; + extraPruneArgs = [ "--stats" ]; + }; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..855d704 --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,5 @@ +{...}: { + imports = [ + ./backup.nix + ]; +}