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, ./data style 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.