From 4389500ccccad7744b8183c3eb215d5d291573b9 Mon Sep 17 00:00:00 2001 From: jasmine Date: Sat, 11 Oct 2025 08:06:00 +0800 Subject: [PATCH 1/2] fix(borgbackup): add network dependencies to onsite services Fixes DNS resolution failures when persistent timers trigger backups after system wake. The NixOS borgbackup module adds network-online.target dependencies to the timer when persistentTimer=true, but systemd timers don't pass their dependencies to the services they trigger. This caused onsite backups to start before the network was ready, resulting in "Could not resolve hostname" errors. Adding after/wants network-online.target directly to the service ensures the backup waits for network availability regardless of how it's triggered (timer or offsite's Wants= dependency). Example failure (Oct 11, 07:43): - Backup started at 07:43:43 (persistent timer caught up) - DNS lookup failed: "Could not resolve hostname viridian.home.arpa" - WiFi connected at 07:43:47 (4 seconds too late) Applied to both fuchsia and viridian onsite backups. --- nixos/fuchsia/services/borgbackup/onsite.nix | 2 ++ nixos/viridian/services/borgbackup/onsite.nix | 2 ++ 2 files changed, 4 insertions(+) diff --git a/nixos/fuchsia/services/borgbackup/onsite.nix b/nixos/fuchsia/services/borgbackup/onsite.nix index 0b4b828..79600dc 100644 --- a/nixos/fuchsia/services/borgbackup/onsite.nix +++ b/nixos/fuchsia/services/borgbackup/onsite.nix @@ -13,6 +13,8 @@ in { # Configure service to wait for completion before marking as active systemd.services."borgbackup-job-onsite" = { + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; }; diff --git a/nixos/viridian/services/borgbackup/onsite.nix b/nixos/viridian/services/borgbackup/onsite.nix index 81fed0f..6e1b669 100644 --- a/nixos/viridian/services/borgbackup/onsite.nix +++ b/nixos/viridian/services/borgbackup/onsite.nix @@ -22,6 +22,8 @@ in { # Configure service to wait for completion before marking as active systemd.services."borgbackup-job-onsite" = { + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; }; From 9fb72e762b56b57bfc7a26d659aa3b7d03586901 Mon Sep 17 00:00:00 2001 From: jasmine Date: Sun, 12 Oct 2025 10:19:42 +0800 Subject: [PATCH 2/2] docs(age): improve readability with structured comments Add section headers and explanatory comments to clarify the purpose of each configuration block, with emphasis on the critical persistent path requirement for early boot secret decryption. --- nixos/common/global/age.nix | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/nixos/common/global/age.nix b/nixos/common/global/age.nix index 521ff70..0a4a7c0 100644 --- a/nixos/common/global/age.nix +++ b/nixos/common/global/age.nix @@ -1,3 +1,5 @@ +# Agenix secret management with YubiKey rekeying +# Handles encrypted secrets for services requiring credentials { config, pkgs, @@ -6,25 +8,34 @@ }: let hostname = config.networking.hostName; in { + # Module imports imports = [ inputs.agenix.nixosModules.default inputs.agenix-rekey.nixosModules.default ]; + # Overlay provides agenix-rekey package and extensions nixpkgs.overlays = [ inputs.agenix-rekey.overlays.default ]; + # CLI tool for manual secret rekeying operations environment.systemPackages = with pkgs; [ agenix-rekey ]; + # Secret decryption configuration + # Use persistent paths to ensure SSH keys are available during early boot + # activation, before impermanence bind mounts /etc/ssh/ + age.identityPaths = [ + "/persist/etc/ssh/ssh_host_rsa_key" + "/persist/etc/ssh/ssh_host_ed25519_key" + ]; + + # YubiKey-based secret rekeying age.rekey = { - # Pubkey for rekeying hostPubkey = ../../${hostname}/ssh_host_ed25519_key.pub; - # Master identity used for decryption masterIdentities = [../users/sajenim/agenix-rekey.pub]; - # Where we store the rekeyed secrets storageMode = "local"; localStorageDir = ./. + "/secrets/rekeyed/${config.networking.hostName}"; };