Backups & snapshots¶
What is backed up: the app configs and databases of the media stack (/volume1/docker: Plex, Sonarr, Radarr, Prowlarr, Bazarr, Seerr, Tautulli, qBittorrent, gluetun, Portainer).
| Layer | Protects against | Where | Schedule | Retention |
|---|---|---|---|---|
| Btrfs snapshots (Snapshot Replication) | Deletion, bad edits, ransomware | NAS | docker hourly · data daily |
more for docker, short for data |
| restic → B2 | NAS loss, fire, theft | Backblaze B2, encrypted | backup nightly · prune and check weekly | daily / weekly / monthly tiers |
| App-native | A bad app update | */Backups/scheduled |
weekly (*arrs), every 3 days (Plex DB) | the app's defaults |
The restic job runs outside the container update window. Exact times and retention counts: see private runbook.
Not backed up off-site: the media (data, about 9 TB). It can be re-acquired, and the *arr databases (backed up) know what to fetch.
What restic includes¶
/volume1/docker, excluding Plex thumbnails/cache/codecs/logs, *arr MediaCover, logs, #snapshot dirs and restic.env. Before each run pre-backup.sh makes consistent SQLite copies (online backup API) of the
Sonarr, Radarr, Prowlarr, Bazarr, Seerr and Plex DBs into restic/dbdump/. When restoring a DB, use the dbdump copy; the live files are only crash-consistent. Setup: restic → B2.
Snapshots setup¶
DSM → Snapshot Replication → Snapshots → select the share → Settings: set the schedule and retention (see private runbook). Keep #snapshot
hidden on data, so Plex and the *arrs don't scan it.
Restore: one file or one app¶
# from a snapshot (docker share)
ls "/volume1/docker/#snapshot/" # GMT<offset>-YYYY.MM.DD-HH.MM.SS folders
# from restic
sudo docker exec restic-backup /scripts/r.sh snapshots
sudo docker exec restic-backup /scripts/r.sh restore latest --target /tmp/r --include /source/docker/sonarr
sudo docker cp restic-backup:/tmp/r/source/docker/sonarr /volume1/docker/_restore-sonarr # inspect, then stop the app and copy into place
For a DB: stop the app, replace <app>.db with the dbdump copy, and delete any stale -wal/-shm files.
Restore after total loss¶
- Rebuild DSM, the shares and the users (NAS setup), keeping the same PUIDs (recorded in the private runbook).
- On any machine with restic, export the four variables from
restic.env(they are in the password manager) and run:restic -r b2:<your-bucket>:<repo-path> restore latest --target ./restore - Copy
restore/source/docker/*→/volume1/docker/, then put the dbdump DBs in place. - Start Portainer on the restored
portainer-ce/data. Every stack and its env comes back. Redeploy them in the order given.
The restic password is the single point of failure
Without RESTIC_PASSWORD, the B2 data can't be read. Keep it and the B2 key in a password manager
and on paper somewhere away from home.
Test restores¶
Quarterly: restore one config file and one dbdump DB, and compare their sha256 with the source. Snapshots: browse one file in #snapshot.