From e679c76e6b39e365b004c321a05d3c3af8907ed8 Mon Sep 17 00:00:00 2001 From: wi11-holdsworth <83637728+wi11-holdsworth@users.noreply.github.com> Date: Mon, 29 Sep 2025 22:46:32 +1000 Subject: [PATCH 1/4] feat: create reusable backup utility function --- modules/nixos/backup.nix | 75 +++++++++++++++++++++++++++++++ modules/templates/web-feature.nix | 3 ++ 2 files changed, 78 insertions(+) create mode 100644 modules/nixos/backup.nix diff --git a/modules/nixos/backup.nix b/modules/nixos/backup.nix new file mode 100644 index 0000000..f262da5 --- /dev/null +++ b/modules/nixos/backup.nix @@ -0,0 +1,75 @@ +service: servicecfg: +{ + # keep-sorted start + pkgs, + config, + lib, +# keep-sorted end +}: +let + notify = + { + tag, + msg, + location, + }: + '' + ${pkgs.curl}/bin/curl \ + -H "X-Tags: ${tag},BorgBackup,Server,${location}" \ + -d "${msg}" \ + ${config.services.ntfy-sh.settings.base-url}/backups + ''; + notifySuccess = + context: + notify { + tag = "tada"; + msg = "Backup succeeded"; + location = "${context}/${service}"; + }; + notifyFailure = + context: + notify { + tag = "rotating_light"; + msg = "Backup failed, check logs"; + location = "${context}/${service}"; + }; + job = + context: contextcfg: + lib.nameValuePair "${context}-${service}" ( + { + compression = "auto,zstd"; + startAt = "*-*-* 04:00:00 Australia/Melbourne"; + prune.keep = { + daily = 7; + weekly = 4; + monthly = 6; + }; + postHook = '' + if [ $exitStatus -eq 0 ]; then + ${notifySuccess context} + else + ${notifyFailure context} + fi + ''; + } + // contextcfg + // servicecfg + ); +in +builtins.listToAttrs [ + (job "onsite" { + repo = "/backup/repo"; + encryption = { + mode = "repokey-blake2"; + passCommand = "cat ${config.age.secrets.borgbackup-server-onsite.path}"; + }; + }) + (job "offsite" { + repo = "vuc5c3xq@vuc5c3xq.repo.borgbase.com:repo"; + encryption = { + mode = "repokey-blake2"; + passCommand = "cat ${config.age.secrets.borgbackup-server-offsite.path}"; + }; + environment.BORG_RSH = "ssh -i /home/srv/.ssh/id_ed25519"; + }) +] diff --git a/modules/templates/web-feature.nix b/modules/templates/web-feature.nix index d101877..77245e2 100644 --- a/modules/templates/web-feature.nix +++ b/modules/templates/web-feature.nix @@ -15,6 +15,9 @@ in enable = true; }; + # backup + borgbackup.jobs = feature { }; + # reverse proxy nginx.virtualHosts."${feature}.fi33.buzz" = { forceSSL = true; -- 2.53.0 From 00c0979552de9f56db4172df6489e0cc8e342d29 Mon Sep 17 00:00:00 2001 From: wi11-holdsworth <83637728+wi11-holdsworth@users.noreply.github.com> Date: Mon, 29 Sep 2025 22:46:42 +1000 Subject: [PATCH 2/4] refactor: backup srv --- modules/nixos/bundles/server.nix | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/nixos/bundles/server.nix b/modules/nixos/bundles/server.nix index 963381b..7e71c78 100644 --- a/modules/nixos/bundles/server.nix +++ b/modules/nixos/bundles/server.nix @@ -1,4 +1,9 @@ -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: let feature = "server"; in @@ -26,6 +31,17 @@ in # keep-sorted end users.groups.media = { }; + + services.borgbackup.jobs = + import ../backup.nix "srv" + { + paths = [ "/srv" ]; + } + { + inherit config; + inherit lib; + inherit pkgs; + }; }; imports = [ ]; -- 2.53.0 From 5e02f195835646259d5001da78e8aae9477ea5d4 Mon Sep 17 00:00:00 2001 From: wi11-holdsworth <83637728+wi11-holdsworth@users.noreply.github.com> Date: Mon, 29 Sep 2025 22:47:04 +1000 Subject: [PATCH 3/4] refactor: backup syncthing --- modules/nixos/features/syncthing.nix | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/modules/nixos/features/syncthing.nix b/modules/nixos/features/syncthing.nix index 47612b5..4f74eea 100644 --- a/modules/nixos/features/syncthing.nix +++ b/modules/nixos/features/syncthing.nix @@ -1,6 +1,7 @@ { config, lib, + pkgs, userName, hostName, ... @@ -62,6 +63,27 @@ in }; }; + # backup + borgbackup.jobs = + # we only need one syncthing host to be backed up + # choose server because borgbackup is the most fleshed out + # on srv currently + if userName == "srv" then + import ../backup.nix feature + { + paths = [ + "/home/srv/.config/syncthing" + "/home/srv/Sync" + ]; + } + { + inherit config; + inherit lib; + inherit pkgs; + } + else + null; + # reverse proxy nginx = { virtualHosts."${feature}.fi33.buzz" = { -- 2.53.0 From 270a34d5b78d47eb809c5d5b189100754900cb6c Mon Sep 17 00:00:00 2001 From: wi11-holdsworth <83637728+wi11-holdsworth@users.noreply.github.com> Date: Mon, 29 Sep 2025 22:47:49 +1000 Subject: [PATCH 4/4] refactor: remove redundant config in borgbackup-srv --- modules/nixos/features/borgbackup-srv.nix | 82 ++--------------------- 1 file changed, 4 insertions(+), 78 deletions(-) diff --git a/modules/nixos/features/borgbackup-srv.nix b/modules/nixos/features/borgbackup-srv.nix index aa81f76..89b07f8 100644 --- a/modules/nixos/features/borgbackup-srv.nix +++ b/modules/nixos/features/borgbackup-srv.nix @@ -1,87 +1,13 @@ { config, lib, - pkgs, ... }: let feature = "borgbackup-srv"; - - secret = "borgbackup"; - notify = - { - tag, - msg, - location, - }: - '' - ${pkgs.curl}/bin/curl -H "X-Tags: ${tag},BorgBackup,Server,${location}" -d "${msg}" ${config.services.ntfy-sh.settings.base-url}/backups - ''; - notifySuccess = - location: - notify { - tag = "tada"; - msg = "Backup succeeded"; - inherit location; - }; - notifyFailure = - location: - notify { - tag = "rotating_light"; - msg = "Backup failed, check logs"; - inherit location; - }; - in { config = lib.mkIf config.${feature}.enable { - services.borgbackup.jobs = - let - srv = location: { - paths = [ - "/srv" - "/home/srv/.config/syncthing" - "/home/srv/Sync" - ]; - - compression = "auto,zstd"; - - startAt = "*-*-* 04:00:00 Australia/Melbourne"; - - prune.keep = { - daily = 7; - weekly = 4; - monthly = 6; - }; - - postHook = '' - if [ $exitStatus -eq 0 ]; then - ${notifySuccess location} - else - ${notifyFailure location} - fi - ''; - }; - - in - { - onsite = srv "onsite" // { - repo = "/backup/repo"; - - encryption.mode = "repokey-blake2"; - encryption.passCommand = "cat ${config.age.secrets.borgbackup-server-onsite.path}"; - }; - - offsite = srv "offsite" // { - repo = "vuc5c3xq@vuc5c3xq.repo.borgbase.com:repo"; - - encryption.mode = "repokey-blake2"; - encryption.passCommand = "cat ${config.age.secrets.borgbackup-server-offsite.path}"; - - environment.BORG_RSH = "ssh -i /home/srv/.ssh/id_ed25519"; - }; - }; - # onsite drive services.udisks2.enable = true; @@ -92,11 +18,11 @@ in # secrets age.secrets = { - "${secret}-server-onsite" = { - file = ../../../secrets/${secret}-server-onsite.age; + "borgbackup-server-onsite" = { + file = ../../../secrets/borgbackup-server-onsite.age; }; - "${secret}-server-offsite" = { - file = ../../../secrets/${secret}-server-offsite.age; + "borgbackup-server-offsite" = { + file = ../../../secrets/borgbackup-server-offsite.age; }; }; }; -- 2.53.0