history-backup — snapshot the irreplaceable data into the parity-protected repo every night¶
~/.local/bin/history-backup <mode>, as angel, no root. Nightly backup at 02:50 — after Immich's 02:00 dump and precious-sync's 02:20, before the 03:30 SnapRAID sync so parity covers the new packs the same night. Sunday 05:30 weekly: forget + prune, restic check --read-data-subset=2%, a restore drill that cmps one random file against the source, then the off-box copy if configured.
Input → Movement → Output¶
Reads the five immich/EmbeddedEra trees plus the out-of-library originals the DB names. Writes one tagged snapshot to the repo; applies the keep policy. Output: the snapshot, a log line backup ok: snapshot <id>, N files, +M MiB new data, last-backup.json, optional Kuma heartbeat.
Why this shape¶
Same guard-and-verify pattern as precious-sync: refuse rather than silently succeed. Guards (history-backup:guards): /mnt/storage is a mountpoint; both source trees exist; the repo exists; the repo is on mergerfs (or it is not parity-protected); no snapraid-sync/snapraid-scrub unit or process is running. Weekly drill exists because a backup never restored is a hypothesis.
Steps¶
guards, thenextra_originals→docker exec immich-postgres psql … where "originalPath" not like '/data/library/%'(cached toextra-originals.listfor a night the DB is down).restic backup --files-from-verbatim <list> --tag nightly --exclude '*.db-shm' --exclude '*.db-wal' --json; parsedata_added,total_files_processed,snapshot_id.restic forget --keep-daily 30 --keep-weekly 12 --keep-monthly 24 --keep-yearly 5(no prune nightly).- Weekly:
forget --prune(counts pack files before/after; ntfy if > 400 removed) →check --read-data-subset=2%→drill(restore to/var/tmp/history-drill,cmp, clean up on PASS) →copyifHISTORY_OFFBOX_REPOis set. first(run once, 2026-09-08 16:35 undersystemd-run --user --unit=history-initial): full backup → drill → report → ntfy. Result: 27 min, 90 G, 5,399 packs, drill PASS. A first attempt launched from a Claude tool shell was killed on purpose at 16:35:46 and produced one spurious "FAILED" ntfy — the reason for the rule below.
Never run it from a Claude tool shell in the background — the memory supervisor kills long children here. systemd-run --user or cron.
If you change this¶
- Hits: the 02:50 slot must stay between the 02:00 dump and the 03:30 sync · retention changes take effect at the next weekly prune · adding a source tree changes repo size and the first-night duration.
- Does not hit: rsnapshot, precious-sync, the array's own data.
Surfaces¶
| Surface | Role |
|---|---|
history-backup status |
one-screen state |
systemctl --user status history-initial |
the initial run, while it lasts |
crontab -l (angel) |
the two lines; the duplicate 02:20 precious-sync line was removed the same day |
See¶
- Objects: history-repo, precious-copy
- Source:
~/.local/bin/history-backup·~/.config/restic/env