compose-backup: One-Command Backup for Docker Compose Stacks

If you’re running multiple Docker Compose services — Nextcloud, Traefik, Gitea, Home Assistant, whatever — you probably have a patchwork of backup scripts. Or worse, no backups at all.

compose-backup fixes that. One command, and every Compose project on your server gets backed up: configs, .env files, override files, and Docker volumes — all compressed into a clean .tar.gz archive you can actually restore from.

Why You Need This

Here’s what usually happens with self-hosted backups:

  1. You set up a service
  2. You tell yourself you’ll “set up backups later”
  3. You add three more services
  4. Your disk dies
  5. You spend a weekend rebuilding everything from memory

compose-backup eliminates this cycle. Run it once, add it to cron, and forget about it.

Installation

curl -fsSL https://raw.githubusercontent.com/bird/compose-backup/main/compose-backup.sh -o /usr/local/bin/compose-backup
chmod +x /usr/local/bin/compose-backup

That’s it. It’s a single Bash script with no dependencies beyond Docker.

Basic Usage

Just run it:

compose-backup

The tool automatically scans common directories (~/docker, /opt/stacks, /srv, etc.) for docker-compose.yml or compose.yml files, then backs up each project it finds.

What Gets Backed Up

For each Compose project, compose-backup saves:

  • docker-compose.yml (and any override files)
  • .env files
  • Config directories (config/, certs/, nginx/, traefik/, ssl/)
  • Named Docker volumes (exported as tar archives)
  • Metadata (hostname, Docker version, timestamps)

Everything lands in a single compressed archive:

~/compose-backups/compose-backup-2026-02-16_030000.tar.gz

Specifying Paths

If your stacks aren’t in standard locations:

compose-backup /opt/my-stacks /home/user/services

Excluding Large Volumes

Some volumes are huge (databases, media libraries). Skip them:

compose-backup --exclude postgres_data --exclude media_files

Backing Up Specific Projects

Only care about certain stacks?

compose-backup --only nextcloud --only traefik

Config-Only Backups

If you handle volume backups separately (like with restic or borgbackup):

compose-backup --no-volumes

Dry Run

See what would be backed up without doing anything:

compose-backup --dry-run

Output:

[[[[[[[[iiiiiiii]]]]]]]]SFWWWWWDcoooooorauuuuuuynnlllllnddddddriun5bbbbbngaaaaacccccccfokkkkkoomuuuuumrpppppppo:::::lDseoentgmhtceriooekpxatnm.erteeierocfataNjliosoCeokrsocuiifmtdnsip(pgtlostaes)p/nseotstp/towptsaper/tctrosakoejtcsspeak/ttcccsga/rtk/icsessttkta./resat.naa/ce.ee)mkdxfos.tin/ckihl)tooomuredia)nsgs)istant)

Restoring from Backup

List your backups:

compose-backup --list

Restore the most recent one:

compose-backup --restore latest

Or restore a specific backup:

compose-backup --restore ~/compose-backups/compose-backup-2026-02-16_030000.tar.gz

The tool extracts everything to a restore directory. From there, copy configs back to your compose directories and restore volumes:

docker run --rm -v nextcloud_data:/dest -v /path/to/restore/nextcloud/volumes:/backup alpine tar xf /backup/nextcloud_data.tar -C /dest

Automating with Cron

Run compose-backup --schedule to get a ready-to-paste crontab line:

# Daily at 3am, keep 7 days
0 3 * * * /usr/local/bin/compose-backup && find ~/compose-backups -name '*.tar.gz' -mtime +7 -delete

Add it with crontab -e and you’re done.

Backup Structure

Here’s what a backup looks like inside:

compo2s0e2-6b-ntga0eric2xatk-teeu1cd.cbfdcbad.bp6loeooaioea/oeoa-_ocnnlckcrccnlc20ukvfuk/ktkkvuk03deimnnuesuemgu20/rgeeepr/preip60-/sxx----st--0c/ttmcmc/em00occeoeoae2/mlltmtm_t-pooapapda1ouu.o.oa.6sddjsjstj_e__seseas0.ddo.o..o3yabnynytn0mt.mma0latllr0.a0tr.atrar.gz

Clean, organized, and self-documenting.

Pairing with selfhost-doctor

If you’re using selfhost-doctor (our one-command server health check), you now have a solid self-hosting toolkit:

  • selfhost-doctor tells you what’s wrong
  • compose-backup makes sure you can recover

Both are single Bash scripts, zero dependencies, and cron-friendly.

Tips

  • Test your restores. A backup you’ve never restored from isn’t a backup — it’s a hope.
  • Store archives off-server. Use rsync, rclone, or even a simple scp to push archives to another machine or cloud storage.
  • Start with --dry-run. See what the tool finds before committing.
  • Use --verbose if you want to see exactly what’s happening during backup.

Requirements

  • Bash 4+
  • Docker with Compose V2 (docker compose)
  • Standard tools: tar, gzip

Get It

curl -fsSL https://raw.githubusercontent.com/bird/compose-backup/main/compose-backup.sh -o /usr/local/bin/compose-backup
chmod +x /usr/local/bin/compose-backup

Source: GitHub


Stop winging your Docker backups. One command, everything saved, sleep better at night.