Btrfs Remote Backups for Docker Hosts on Debian 12
In my home lab, I run multiple Docker hosts on Debian 12 VMs inside Proxmox. While Proxmox Backup Server (PBS) already handles full VM backups, I wanted an additional layer for my Docker containers — specifically the docker-compose setups and persistent data under /srv/containers/apps. This post explains how I implemented remote Btrfs backups using btrbk, including handling multiple hosts and automating via systemd.
Why Btrfs Backups?
Full VM backups are great for disaster recovery, but they can be overkill if you just need your Docker containers and volumes. With Btrfs, you can snapshot subvolumes incrementally, making restores faster and more flexible. I focused on:
/srv/containers/apps— persistent Docker data anddocker-composeconfigs- Optional:
/srv/containers/dockerdata— Docker volumes (may be skipped to save space) - Remote backups across three hosts:
docker-host-primary,docker-host-01, anddocker-host-02 - Target: external Btrfs disk for portability in case the main PVE host fails
Setting Up the External Backup Disk
I mounted my Btrfs disk under /srv/backup with the following fstab entry:
UUID=XXX-YYY-AAA-BBB-111 /srv/backup btrfs defaults,nofail,x-systemd.automount,compress=zstd,autodefrag 0 0
This ensures it automounts at boot, even if not present.
Btrbk Configuration
I opted to skip local snapshots, relying solely on the remote/incremental snapshots:
timestamp_format long
transaction_log /var/log/btrbk.log
incremental yes
lockfile /var/lock/btrbk.lock
target_preserve_min no
target_preserve 14d 6w 14m
target /srv/backup
volume /srv/containers
group vm docker-host-primary
subvolume apps
snapshot_name docker-host-primary_apps
volume ssh://docker-host-01.internal/srv/containers
group vm docker-host-01
subvolume apps
snapshot_name docker-host-01_apps
volume ssh://docker-host-02.internal/srv/containers
group vm docker-host-02
subvolume apps
snapshot_name docker-host-02_apps
Notes on Remote SSH Access
- Created a dedicated
btrbkuser on each host - Configured SSH keys in
/etc/btrbk/ssh/btrbk_ed25519 - Automate user creation and configuration deployment via Ansible
- Set proper
sudoprivileges for Btrfs commands:
btrbk ALL=(ALL) NOPASSWD: /usr/bin/btrfs subvolume *, /usr/bin/btrfs send *, /usr/bin/btrfs receive *, /usr/bin/btrfs subvolume snapshot *, /usr/bin/btrfs subvolume show *, /usr/bin/btrfs subvolume delete *, /usr/bin/readlink *
- Ensured
/srv/containersis readable bybtrbkfor remote operations
Testing the Backup
- Dry-run command:
sudo btrbk dryrun
Expected output shows local and remote snapshots being created without actually writing data:
/srv/containers/apps
+++ /srv/backup/docker-host-primary_apps.20250903T1312
>>> /srv/backup/docker-host-01_apps.20250903T1312
>>> /srv/backup/docker-host-02_apps.20250903T1312
Automating with Systemd
I created a simple btrbk.service:
[Unit]
Description=Run btrbk backup
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/btrbk run
StandardOutput=journal
And a daily timer at 03:00:
[Unit]
Description=Run btrbk daily
[Timer]
OnCalendar=03:00
Persistent=true
[Install]
WantedBy=timers.target
Activate with: sudo systemctl daemon-reload sudo systemctl enable --now btrbk.timer
The Persistent=true ensures missed runs are executed once the system is back online.
Retention & Snapshot Cleanup
I let btrbk handle snapshot retention automatically via target_preserve. Manual deletion is generally discouraged because snapshots are incremental and dependent.
Summary
- Btrbk provides lightweight, incremental backups for Btrfs subvolumes
- Remote backups via SSH allow multiple hosts to consolidate snapshots
- Systemd timers automate daily runs and persist missed backups
- External Btrfs disks provide portability for disaster recovery scenarios
- This setup complements full VM backups via Proxmox, giving faster recovery for Docker containers without restoring entire VMs.