Four independent copies, four different ways to lose them.
sonda.rogerle.com · restic 0.19.1 · reviewed 2026-09-02
This box holds four separate backup legs. They are not redundancy for its own sake: each one survives a failure the others do not. A single shared repo survives a dead server but not a bad passphrase; a local mirror survives the remote host vanishing but not the building it sits in.
restic pushes /etc, /root, /home over SFTP to the
shared fleet repo, deduplicated across hosts and scoped by hostname.
sftp:backups@backups.rogerle.com:/home/backups/restic-rl
restic backup --host "$HOST" --tag "$HOST" --tag nightly
Retention runs Sundays 05:00: --keep-daily 14 --keep-weekly 8
--keep-monthly 12 --prune, always --host "$(hostname -f)" so one box
can never prune another's snapshots. Integrity check 06:30 on the 1st.
restic copy pulls Repo A into a second repository on this box's own disk —
currently 101 GB under /backup/restic-mirror. Different
hardware, different continent, different failure mode.
RESTIC_FROM_REPOSITORY=sftp:backups@backups.rogerle.com:/home/backups/restic-rl
RESTIC_REPOSITORY=/backup/restic-mirror
backup done and deliberately not on
mirror-pull done.The crew's shared memory. Helsinki pushes the Porão database here nightly; the
local MariaDB schema porao (files, file_versions,
tokens) backs the dormant failover at mcp.rogerle.net, deployed
by Calafate 2026-06-13. Engine lives in /opt/porao.
tar + zstd of /etc /home /opt /root /srv /var/spool/cron, uploaded through
an rclone crypt remote so Google stores ciphertext only. Keeps
6 weekly copies (RETENTION_COUNT=6); the oldest is deleted
after a successful upload, never before.
projects/rclone.md.| When | What | Leg |
|---|---|---|
| 03:30 daily | restic backup → Repo A | 1 |
| 04:17 daily | Helsinki → Sonda Porão push (inbound) | 3 |
| 04:30 daily | restic mirror-pull → Repo B | 2 |
| 05:00 Sun | restic forget + prune | 1 |
| 05:30 Sun | encrypted Drive upload | 4 |
| 06:30 monthly | restic check (integrity) | 1 |
Ordering is deliberate: the mirror pulls after the push, and prune runs before the Drive upload so the weekly tarball reflects a pruned repo. Anything new goes outside these windows.
All four legs append to /var/log/rl-backup.log. The success markers are
what monitoring keys on, so they matter more than they look:
=== 2026-09-02T03:30:55+01:00 backup done host=sonda.rogerle.com ===
=== 2026-09-02T04:54:49+01:00 mirror-pull done ===
[2026-08-30T05:37:36+01:00] gdrive-backup: END — success (3.5GB uploaded, ...)
site-health-check --json exposes backups.restic_last and
backups.gdrive_last_success from these lines. Drive is weekly —
six days old is normal; alert past eight, not past one.
Roughly five minutes. There is no restic init — the repo already
exists and initialising over it would be a very bad afternoon.
# EPEL provides restic on AlmaLinux 8 / 9 / 10
dnf install -y epel-release && dnf install -y restic
ssh-copy-id backups@backups.rogerle.com
ssh backups@backups.rogerle.com 'echo OK'
scp sonda.rogerle.com:/etc/cron.d/restic-backup /etc/cron.d/restic-backup
# then MOVE YOUR SLOT so boxes do not all hit the repo at once:
sed -i 's|^30 3 |15 4 |' /etc/cron.d/restic-backup # backup -> 04:15
sed -i 's|^0 5 |45 5 |' /etc/cron.d/restic-backup # prune -> 05:45 Sun
Then add legs 2–4 as the box warrants. A box holding nothing unique may legitimately stop at leg 1 — but that is a decision to make out loud, not by forgetting.
restic restore
--target /tmp/x --include /etc/hostname latest is enough to prove the repo,
the password file and the SFTP path all work together.