From 441f3c519deb5242440dcc138780d0bb5dc95914 Mon Sep 17 00:00:00 2001 From: smalldave Date: Mon, 31 Aug 2026 18:42:58 +0000 Subject: [PATCH] nixos/syncoid: catch up missed timer runs (Persistent=true) The generated timers previously carried only OnCalendar=, so with systemd's default Persistent=false a replication run scheduled while the machine was powered off was silently skipped: no catch-up at boot, no failed unit, `systemctl list-timers` shows LAST PASSED=-. Declare the timer explicitly with Persistent=true so missed windows are executed at the next boot, matching the other backup modules (services.restic defaults Persistent=true in its timerConfig, btrbk hard-codes it, borgbackup exposes it). Users who deliberately want missed runs dropped can mkForce Persistent=false on the timer unit. Assisted-by: Claude Code (claude-fable-5) --- nixos/modules/services/backup/syncoid.nix | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix index 8bfb3d70a6e6..da5a21b37fb7 100644 --- a/nixos/modules/services/backup/syncoid.nix +++ b/nixos/modules/services/backup/syncoid.nix @@ -362,7 +362,6 @@ in { description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}"; after = [ "zfs.target" ]; - startAt = cfg.interval; # syncoid may need zpool to get feature@extensible_dataset path = [ "/run/booted-system/sw/bin/" ]; serviceConfig = { @@ -473,6 +472,23 @@ in ] ) ) cfg.commands; + + systemd.timers = lib.concatMapAttrs ( + name: c: + lib.optionalAttrs + (config.systemd.services."syncoid-${escapeUnitName name}".enable && cfg.interval != [ ]) + { + "syncoid-${escapeUnitName name}" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfg.interval; + # Backup timers should catch up on missed windows (e.g. the + # machine was powered off), like restic and btrbk do. + Persistent = true; + }; + }; + } + ) cfg.commands; }; meta.maintainers = with lib.maintainers; [