From 34c736423f8b24e1082766bfe6747fe9326b7a13 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 20 Feb 2026 11:15:38 +0100 Subject: [PATCH] adds declarative json config for backrest --- hosts/dnsc-server/default.nix | 7 +++- modules/backrest/default.nix | 66 ++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/hosts/dnsc-server/default.nix b/hosts/dnsc-server/default.nix index 8036311..e219bde 100644 --- a/hosts/dnsc-server/default.nix +++ b/hosts/dnsc-server/default.nix @@ -36,7 +36,12 @@ # Secrets age = { identityPaths = [ "${config.users.users.dennis.home}/.ssh/id_ed25519" ]; - secrets."restic/password".file = ../../secrets/restic/password.age; + secrets."restic/password" = { + file = ../../secrets/restic/password.age; + # backrest reads the password via "file:" in its repo config + group = "backrest"; + mode = "0440"; + }; }; # Nix Settings diff --git a/modules/backrest/default.nix b/modules/backrest/default.nix index f3d39bf..a7f1da2 100644 --- a/modules/backrest/default.nix +++ b/modules/backrest/default.nix @@ -1,8 +1,60 @@ { + config, pkgs, lib, ... }: +let + # Declarative backrest config referencing the existing restic repo. + # The password is read at runtime from the agenix secret path via + # BACKREST_VAR_RESTIC_PASSWORD, which backrest expands as ${RESTIC_PASSWORD} + # inside the repo env block. + backrestConfig = builtins.toJSON { + modno = 1; + instance = "dnsc-server"; + repos = [ + { + id = "dnsc-storage"; + uri = "sftp:dnsc-storage:restic/dnsc-server"; + password = "file:${config.age.secrets."restic/password".path}"; + flags = [ + "-o" + "sftp.args=-i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new" + ]; + prunePolicy = { + schedule = { + disabled = { }; + }; + }; + checkPolicy = { + schedule = { + disabled = { }; + }; + }; + } + ]; + plans = [ + { + id = "dnsc-storage-plan"; + repo = "dnsc-storage"; + paths = [ + "/home/dennis/notes" + "/main/share" + "/data/actual-server" + ]; + schedule = { + disabled = { }; + }; + retention = { + policyKeepLastN = 3; + }; + } + ]; + auth = { + disabled = true; + }; + }; +in { environment.systemPackages = lib.mkAfter ( with pkgs; @@ -20,6 +72,15 @@ description = "Backrest service user"; }; + # Write the declarative config at activation time. + # The file is owned by root (readable by backrest via group or world-read) + # but we set it 640 and add backrest to read it via the service's User=. + environment.etc."backrest/config.json" = { + text = backrestConfig; + mode = "0440"; + group = "backrest"; + }; + systemd.services.backrest = { enable = true; description = "Restic GUI"; @@ -29,7 +90,7 @@ environment = { BACKREST_PORT = "9004"; BACKREST_RESTIC_COMMAND = "${pkgs.restic}/bin/restic"; - BACKREST_CONFIG = "/var/lib/backrest/config"; + BACKREST_CONFIG = "/etc/backrest/config.json"; BACKREST_DATA = "/var/lib/backrest/data"; }; @@ -40,6 +101,9 @@ ExecStart = "${pkgs.backrest}/bin/backrest"; Restart = "on-failure"; RestartSec = "5s"; + # Allow backrest to read root's SSH key for SFTP access + ReadOnlyPaths = [ "/root/.ssh/id_ed25519" ]; + SupplementaryGroups = [ "shadow" ]; }; }; }