Backing Up Self-Hosted Services on Raspberry Pi with Restic and Borg
This site has walked through building a Raspberry Pi NAS, a Jellyfin media server, an Immich photo library, a Vaultwarden password vault, a Home Assistant hub, and a K3s cluster — and none of those guides cover what happens when the SD card or SSD dies, a bad update corrupts a database, or a container's data volume gets wiped by mistake. Imaging the whole SD card to a network share (covered elsewhere on this site) protects the OS and boot config, but it's a blunt instrument for the data actually living inside your self-hosted services — a 30GB Immich photo library or a growing Jellyfin library doesn't need a full disk image taken nightly, it needs proper incremental, deduplicated backup of just the data that changed. That's what Restic and Borg are built for, and neither gets much attention in maker circles despite being the standard tools for exactly this job in the self-hosting world.
Why Not Just rsync or a Cron Copy Job
A plain rsync or cp job to a network share works until you need history — if a database gets corrupted three days ago and nobody noticed until today, a simple mirrored copy has already mirrored the corruption. Restic and Borg both keep space-efficient snapshots: every backup run only stores the data that changed since the last one (via content-defined chunking and deduplication), but each snapshot is still individually restorable as a complete point-in-time copy. A week of daily snapshots of a 30GB photo library might only cost a few hundred MB of extra storage beyond the first full backup, while still letting you restore to any of those seven days independently.
Restic vs Borg
ResticBorgBackupWritten inGo — single static binary, trivial to install on ARMPython — needs a matching Python environment, slightly more setup on a PiRemote backendsS3-compatible (including Backblaze B2, self-hosted MinIO), SFTP, REST server, local, and more — very flexibleSFTP/SSH and local primarily, via Borg's own repo formatEncryptionAlways encrypted client-side by defaultAlways encrypted client-side by defaultDeduplicationContent-defined chunking across the whole repoContent-defined chunking across the whole repo, generally excellent ratiosBest fit for a Pi setupBacking up to cloud object storage (B2, S3) or a REST server on a second machineBacking up to another Pi, NAS, or any SSH-reachable box on the LANEither is a solid choice; Restic's single-binary install and native cloud backend support make it the easier starting point if the backup target is off-site cloud storage, while Borg is a very natural fit if the target is another machine on the same network reachable over SSH.
What to Actually Back Up
For a typical Docker Compose self-hosted stack, back up the bind-mounted data directories and any named volumes, not the container images themselves — images are reproducible from your docker-compose.yml and can be re-pulled, but the data inside them (Immich's photo library and Postgres database, Vaultwarden's vault, Home Assistant's config and history database) is not. For anything backed by a database — Postgres for Immich, SQLite for many lighter services — take an application-consistent dump (pg_dump, or an SQLite .backup command) before the file-level backup runs, rather than backing up live database files directly, which risks capturing a mid-write, inconsistent state.
Basic Restic Workflow on a Pi
- Install the ARM64 Restic binary release, or via apt on recent Raspberry Pi OS.
- Initialize a repository on the chosen backend: restic init --repo b2:my-bucket:pi-backups for Backblaze B2, or restic init --repo sftp:user@host:/backups/pi for another machine over SSH.
- Run a backup of your Docker data directories: restic backup /home/pi/docker-data --exclude-caches.
- Set a retention policy so old snapshots get pruned automatically rather than growing forever: restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune.
- Schedule both commands with a nightly cron job or a systemd timer, and log output somewhere you'll actually check.
Verify Restores, Not Just Backups
The single most common backup failure isn't a missing backup — it's a backup nobody ever tested restoring, that turns out to be incomplete or corrupted exactly when it's needed. Both tools support mounting a snapshot as a browsable filesystem (restic mount, borg mount) without doing a full restore, which makes spot-checking painless. Do a real, full test restore to a spare directory at least once after initial setup, and periodically afterward — an untested backup is a hope, not a backup.
Where This Fits with SD Card Imaging
SD card or boot-disk imaging (covered in this site's SD card backup guide) and application-level Restic/Borg backups solve different problems and both are worth having: a disk image gets you back to a bootable system fast after hardware failure, while Restic/Borg snapshots protect the actual data inside your services with history and off-site redundancy that a single disk image copy doesn't provide. A reasonable setup runs both — a weekly or monthly full disk image for fast bare-metal recovery, and nightly Restic or Borg snapshots of the data directories that actually change day to day.
Off-Site Matters
A backup that lives on a second drive plugged into the same Pi, in the same room, protects against drive failure and not much else — fire, theft, and power surges take out both copies together. Point at least one backup target somewhere physically separate: a cheap Backblaze B2 bucket (Restic's per-GB cost there is low enough that a modest self-hosted stack costs pennies a month to protect), a relative's house running a second Pi or NAS reachable over Tailscale or WireGuard, or any other genuinely off-site location.
Related Guides
- Auto-Backup Your Raspberry Pi SD Card to a Network Share
- Self-Hosting Jellyfin Media Server on a Raspberry Pi: Hardware Transcoding and Remote Access
- How to Install Klipper on Any 3D Printer: Complete Setup Guide
- How to Set Up OpenCV Machine Vision on a Raspberry Pi
- Raspberry Pi: Complete Headless Setup Guide (No Monitor Needed)
- Raspberry Pi: Headless OS Setup
- How to Set Up a Raspberry Pi Headless with SSH and WiFi
- How to Install and Configure Pi-hole on Raspberry Pi