Scheduling restic Backups
Run the backup script daily, on time, in the right timezone. Prefer a systemd timer (timezone-aware, handles missed runs, integrates with OnFailure= alerting). Use cron only on non-systemd hosts. Ready-to-paste units are in references/systemd-units.md.
Do not enable the schedule until verify-backup passes (first run + check + test-restore). Install the units now, enable them later.
systemd timer (preferred)
Two units in /etc/systemd/system/:
restic-backup.service (oneshot, niced so it doesn't starve the host):
[Unit]
Description=restic backup to object storage (encrypted)
Wants=network-online.target
After=network-online.target docker.service
[Service]
Type=oneshot
Nice=10
IOSchedulingClass=idle
ExecStart=/usr/local/sbin/restic-backup.sh
TimeoutStartSec=6h
restic-backup.timer:
[Unit]
Description=Daily restic backup
[Timer] 03:00:00
Persistent=true
RandomizedDelaySec=1800
[Install]
WantedBy=timers.target
Reload and verify the calendar resolves before enabling:
systemctl daemon-reload
systemd-analyze calendar "*-*-* 03:00:00" --iterations=3 # prints the next 3 run times
Timezone
systemd OnCalendar uses the server's local time by default — set the server timezone with timedatectl set-timezone Europe/Kyiv, or pin it per-timer (systemd ≥ 252):
[Timer] 03:00:00
Timezone=Europe/Kyiv
systemd-analyze calendar "*-*-* 03:00:00 Europe/Kyiv" checks a zoned expression. Persistent=true runs a missed backup after downtime; RandomizedDelaySec spreads load and avoids hammering R2 at exactly the same second.
cron fallback (non-systemd hosts)
/etc/cron.d/restic-backup — set the timezone and prevent overlapping runs with flock:
CRON_TZ=Europe/Kyiv
0 3 * * * root /usr/bin/flock -n /var/run/restic-backup.lock /usr/local/sbin/restic-backup.sh
CRON_TZ makes the schedule timezone-aware. flock -n ensures a long backup never overlaps the next run. cron's PATH is minimal — the script sets its own absolute PATH (see backup-script).
Enable (only after verification)
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer # shows NEXT run time
Gotchas
- Enable only after
verify-backup— never schedule an unverified backup. daemon-reloadafter editing units, or systemd runs the old definition.Persistent=truecatches runs missed while the host was off.- Avoid concurrent runs on one repo —
flockfor cron; systemd oneshot won't overlap itself, but watch out for a manual run colliding with the timer (causes a repo lock → seetroubleshoot). - Timezone source — system tz vs per-timer
Timezone=vs cronCRON_TZ; pick one and verify withsystemd-analyze calendar. - Schedule the periodic
check(frommonitoring) off the backup hour to avoid repo-lock contention.
What this skill does NOT cover
- The script itself →
backup-script - First run + enabling gate →
verify-backup - Failure alerts /
OnFailure=wiring →monitoring