fix(borgbackup): prevent race conditions and improve reliability

Fixes multiple issues with borgbackup service coordination:

1. Race condition between onsite/offsite backups
   - Set Type=oneshot to ensure services wait for completion
   - Added Wants= dependency to trigger onsite when offsite runs
   - Prevents snapshot path collision at /btrfs-subvolumes

2. Network unavailability after sleep/wake
   - Added persistentTimer=true to onsite backups
   - NixOS module now auto-adds network-online.target dependencies
   - Fixes DNS resolution failures for SSH repos

3. Data loss risk from missed backups
   - Persistent timers ensure backups run on wake if missed
   - Protects work done before sleep from being unbackored

4. Duplicate onsite runs at midnight
   - Removed 15-minute stagger (00:15 -> 00:00)
   - Systemd deduplicates services in same transaction
   - Onsite now runs once, not twice

Applied to both fuchsia and viridian for consistency.
This commit is contained in:
♥ Minnie ♥ 2025-10-09 11:30:00 +08:00
parent 15b4851e8e
commit a276fdf53a
Signed by: jasmine
GPG key ID: 8563E358D4E8040E
4 changed files with 30 additions and 2 deletions

View file

@ -15,7 +15,11 @@
# Wait for onsite backup to complete before starting offsite
systemd.services."borgbackup-job-offsite" = {
wants = ["borgbackup-job-onsite.service"];
after = ["borgbackup-job-onsite.service"];
serviceConfig = {
Type = "oneshot";
};
};
services.borgbackup.jobs."offsite" = {
@ -79,7 +83,7 @@
environment.BORG_RSH = "ssh -i /etc/ssh/ssh_host_ed25519_key";
compression = "zstd,9";
startAt = "*-*-* 00:15:00"; # Daily at 12:15 AM
startAt = "daily"; # Daily at midnight
# Ensure backup runs on next boot if system was asleep
persistentTimer = true;

View file

@ -11,6 +11,13 @@ in {
"d /btrfs-subvolumes 0755 root root -"
];
# Configure service to wait for completion before marking as active
systemd.services."borgbackup-job-onsite" = {
serviceConfig = {
Type = "oneshot";
};
};
services.borgbackup.jobs."onsite" = {
# Allow writing to staging directory
readWritePaths = [ "/btrfs-subvolumes" ];
@ -73,6 +80,9 @@ in {
compression = "zstd,9";
startAt = "hourly";
# Ensure backup runs on wake if system was asleep
persistentTimer = true;
# Match snapper retention policy
prune.keep = {
hourly = 24;

View file

@ -15,7 +15,11 @@
# Wait for onsite backup to complete before starting offsite
systemd.services."borgbackup-job-offsite" = {
wants = ["borgbackup-job-onsite.service"];
after = ["borgbackup-job-onsite.service"];
serviceConfig = {
Type = "oneshot";
};
};
services.borgbackup.jobs."offsite" = {
@ -98,7 +102,7 @@
environment.BORG_RSH = "ssh -i /etc/ssh/ssh_host_ed25519_key";
compression = "zstd,9";
startAt = "*-*-* 00:15:00"; # Daily at 12:15 AM
startAt = "daily"; # Daily at midnight
# Ensure backup runs on next boot if system was asleep
persistentTimer = true;

View file

@ -20,6 +20,13 @@ in {
"d /btrfs-subvolumes 0755 root root -"
];
# Configure service to wait for completion before marking as active
systemd.services."borgbackup-job-onsite" = {
serviceConfig = {
Type = "oneshot";
};
};
services.borgbackup.jobs."onsite" = {
# Allow writing to staging directory
readWritePaths = [ "/btrfs-subvolumes" ];
@ -99,6 +106,9 @@ in {
compression = "zstd,9";
startAt = "hourly";
# Ensure backup runs on wake if system was asleep
persistentTimer = true;
# Match snapper retention policy
prune.keep = {
hourly = 24;