Backing Up a Home Server Before You Trust It

by · Wednesday. Jul 22, 2026

When the server stops being a toy

For the early parts of this series, my home server was basically a sandbox. If it broke, I’d shrug, rebuild it, and learn something. That attitude was fine while everything on it was replaceable. It stopped being fine the moment Immich held the only copy of some phone videos and Paperless held scanned documents I’d shredded the originals of.

A home server becomes real when you stop treating it like a toy and start protecting the data. So before I go any further, I want backups I actually trust. Not a vague intention to “set that up someday.” An actual job that runs, lands somewhere safe, and has been tested.

What this solves

  • Separates data that matters from data I can re-download.
  • Gets a real local backup running on a schedule.
  • Decides the offsite tradeoff honestly instead of pretending RAID is a backup.
  • Tests a restore before I depend on it.

This builds directly on the storage split I set up back in part 5, where I started keeping app config and user media in separate trees.

What actually matters vs what’s replaceable

The first job isn’t technical. It’s sorting my data into two piles: irreplaceable and replaceable. Backing up everything equally wastes disk and makes restores slower, so I’d rather be honest about what I’d actually cry over.

Replaceable, in my setup:

  • Jellyfin movies and shows (I can re-rip or re-acquire)
  • Audiobooks and podcasts (re-downloadable)
  • yt-dlp’s curated shelf (the channel list matters more than the files)
  • The qBittorrent download folder

Irreplaceable:

  • Immich photos and videos from my phone
  • Paperless documents and its database
  • Every app’s config and docker-compose.yml

That last line is the one people skip. The media is the obvious thing, but the configs are what let me rebuild the server without re-deriving every setting from memory. Losing my Caddy and Pi-hole config wouldn’t lose data, but it’d cost me an evening I don’t want to spend twice.

The backup targets

Because I kept config under /srv/appdata/ and big media under /srv/storage/, the list of paths I care about is short and obvious. That folder discipline is paying off here more than anywhere else.

The paths I back up:

/srv/appdata/                 # all app config + compose files
/srv/storage/pictures/immich  # the photo library
/etc/caddy/Caddyfile          # reverse proxy config

Paperless and Immich both run a database, and a database needs care. Copying live Postgres files while the container is writing can give you a corrupt snapshot. So for those, I either stop the stack briefly or use the app’s own database dump. Immich’s backup and restore docs spell out the difference between copying files and dumping the database, and it’s worth reading before you trust a naive cp.

My approach for the databases is a short script that runs pg_dump inside the container, writes the dump next to the appdata, and then lets the file backup pick it up like everything else.

A local copy first

Before anything offsite, I want a local copy on a separate physical drive. If the laptop’s main disk dies, I don’t want my only backup to die with it. So the local target is an external USB drive mounted at /srv/backup.

The tool is restic. It does deduplication, encryption, and snapshots, which means I’m not just overwriting one copy with a newer broken one. A daily snapshot keeps history, so if Paperless corrupts something and I don’t notice for two days, I can still go back.

The rough shape:

export RESTIC_REPOSITORY=/srv/backup/restic
export RESTIC_PASSWORD_FILE=/root/.restic-pass

restic backup \
  /srv/appdata \
  /srv/storage/pictures/immich \
  /etc/caddy/Caddyfile

I wrapped that in a small script and put it on a systemd timer, the same pattern from part 8. A daily run at a quiet hour is plenty for a home server. I also added restic forget --keep-daily 7 --keep-weekly 4 --prune so the repo doesn’t grow forever.

The offsite tradeoff

Here’s where I had to be honest. A local backup protects against a dead drive. It does not protect against theft, fire, or me fat-fingering both drives at once. Offsite is the only thing that covers those, and offsite is where the convenience-versus-effort tradeoff gets real.

My middle ground: photos and documents go offsite, media doesn’t. Re-uploading hundreds of gigabytes of movies to cloud storage every month is slow and pointless when I can just re-acquire them. But the Immich and Paperless data is small enough and important enough to justify it.

restic can push to an offsite repo too, encrypted before it leaves the house, which matters because I don’t want a cloud provider holding my family photos in the clear. I run a second, smaller backup job for just the irreplaceable paths and send it to a remote repo. It’s the calm-server version of the 3-2-1 rule: not maximalist, just enough that one bad day can’t erase the things I can’t recreate.

The part everyone skips: testing a restore

A backup you’ve never restored is a hope, not a backup. This is the step I almost skipped too, because everything “looked” fine and testing felt like extra work. But an untested backup has a way of failing exactly when you need it.

So I tested it. I restored into a throwaway folder and checked the files were actually there and readable:

restic restore latest --target /tmp/restore-test
ls /tmp/restore-test/srv/storage/pictures/immich

Then I did the scarier test: I spun up Paperless from the restored config and database dump in a temporary spot and confirmed it actually came back with my documents. The first time I tried, my database dump was empty because I’d pointed pg_dump at the wrong container name. I’d never have known without testing. That single dry run is the whole reason this post exists.

Now I trust the backups, because I’ve seen them come back. That’s the difference between a server I tinker with and one I actually rely on.

What’s next

With data I care about protected and a restore I’ve actually verified, the server finally feels real. Next up, I look at remote access: how to reach these services from outside the house without throwing away the local-first philosophy that started this whole project.