Backups 101
The 3-2-1 basics applied to a homelab - backing up compose volumes and configs, not just "hoping the disk doesn't die."
This is the least optional page in the Beginner tier. Everything else here is about adding capability; this one is about not losing what you've built.
The 3-2-1 rule, applied to a homelab
See 3-2-1 backup rule in the glossary for the general definition. In homelab terms:
- 3 copies - the live data, plus at least two backups.
- 2 different media - not two copies on the same disk. An external USB drive is a genuinely fine second copy for this tier.
- 1 off-site - a cloud storage target (Backblaze B2, a relative's house with a drive, anything genuinely not in the same building) so a fire or theft doesn't take every copy at once.
You don't need all of this from day one, but know what you're missing. A single external drive plugged into the server is a backup, not the backup - it's better than nothing and it's not 3-2-1 yet.
What actually needs backing up
For a Docker-based homelab, it's narrower than people expect:
- Bind-mounted volumes - the
./config,./datastyle folders from your compose files (see Docker Compose Basics). This is where service state, databases, and media library metadata live. - The compose files themselves - small, text, trivial to back up,
but easy to forget. Keep your
~/homelab/folder (or wherever your compose files live) in the backup scope, ideally in a git repo too. - Anything not reproducible from the above - your actual media library, for instance, if re-acquiring it would be painful. Whether that's worth backing up (vs. just re-ripping/re-downloading) is a judgment call about how replaceable the content is.
You generally do not need to back up Docker images themselves - they're re-downloadable from their registry on demand.
A simple approach: restic to an external drive and B2
restic is a free, encrypted, deduplicating backup tool that works well for exactly this use case.
sudo apt install restic
restic repositories are always encrypted and need a password. Set one before doing anything else, so it's available for the automated runs below rather than restic prompting interactively every time:
export RESTIC_PASSWORD="a-real-generated-password"
Save that same value somewhere durable (your password manager, not
just this shell session) - a repository without its password is
unrecoverable, same as losing the Vaultwarden ADMIN_TOKEN. For the
cron job or systemd timer mentioned below, put it in an
EnvironmentFile (systemd) or source it from a restricted-permission
file rather than hardcoding it in the crontab itself.
Initialize a repository on an external drive:
restic init --repo /mnt/backup-drive/homelab-restic
Back up your homelab folder:
restic backup ~/homelab --repo /mnt/backup-drive/homelab-restic
Restic only stores changed data on each run (deduplication), so repeated backups after the first are fast and small. Automate it with a cron job or systemd timer running nightly - see cron/timer setup in your distro's documentation if you haven't used either before.
For the off-site copy, restic supports Backblaze B2, S3-compatible storage, and several others directly:
export B2_ACCOUNT_ID=xxx
export B2_ACCOUNT_KEY=xxx
restic init --repo b2:your-bucket-name:homelab
restic backup ~/homelab --repo b2:your-bucket-name:homelab
Test the restore before you need it
A backup you haven't restored from is a theory, not a backup. Once it's running, actually test a restore into a scratch folder:
restic restore latest --repo /mnt/backup-drive/homelab-restic --target /tmp/restore-test
Confirm the files look right. Do this now, while it's a five-minute exercise, not during an actual outage when it's a crisis.
With real backups in place, the last thing worth doing before calling this tier done is a sanity check on what it's actually costing you to run - see Cost and Power Tracking.
Next: Cost and Power Tracking.