sabon¶
Label-driven restic backups for Docker — declare a backup in the service's own Compose labels, and sabon discovers it and backs it up with restic on a schedule. Per-app, per-target repositories you restore from with one command — including full disaster recovery when the app is gone.
-
🏷️ Declared next to the service
The backup spec lives in the app's own Compose labels — not a central, disconnected config.
-
📦 Per-app, per-target repos
Each app gets isolated restic repositories, so retention and restores stay independent and the blast radius stays small.
-
🔐 Incremental & encrypted
Movers run restic: each run stores only changed data, deduplicated and client-side encrypted; a scheduled
restic checkverifies repository integrity. -
🗃️ Any volume driver
Movers mount volumes by name, so named volumes (any driver) and bind mounts back up alike.
-
🐝 Standalone or Swarm
Drives a single Docker host by default; on a Swarm manager it drives the whole cluster, running each mover as a node-pinned service.
-
📸 Atomic or best-effort snapshots
snapshot: zfsbacks up from a crash-consistent ZFS snapshot — no app downtime;autosnapshots what it can and mounts the rest live. -
♻️ Restore anywhere
One command restores a snapshot into a staging directory or in place — even if the original app is gone.
-
📊 Metrics & alerts
Prometheus metrics, health endpoints, ready-made alert rules, and notifications catch silent failures.
-
🔌 HTTP control API
An optional, token-authenticated API to trigger runs and browse durable run history — for dashboards and automation.
Pre-1.0
Early-stage software — expect occasional breaking changes to labels or configuration before 1.0. Pin an image tag and skim the release notes when upgrading.
Quick start¶
Label a container and run sabon alongside it:
services:
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx
volumes:
- paperless-data:/usr/src/paperless/data
labels:
sabon.enable: "true"
sabon.backup: |
repo: paperless
auto: true # back up this container's own volumes
sabon:
image: ghcr.io/davidborzek/sabon:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./targets.yaml:/etc/sabon/targets.yaml:ro
- /mnt/backup:/mnt/backup
environment:
RESTIC_PASSWORD: change-me
restart: unless-stopped
volumes:
paperless-data:
With a targets.yaml that points at where the repos live:
targets:
- name: onsite
path: /mnt/backup # repo = /mnt/backup/paperless
schedule: "0 0 */6 * * *" # every 6 hours (6-field cron)
retention: { daily: 7, weekly: 5 }
sabon discovers the paperless container, and every six hours a mover container
runs restic backup of paperless-data into /mnt/backup/paperless, then
applies retention. Run one immediately without waiting for the schedule:
Running Docker Swarm?
sabon can drive a whole cluster too, running each mover as a node-pinned service — see Docker Swarm (experimental).
Documentation¶
- Configuration — every
SABON_*env var and the targets-file schema. - Labels — the
sabon.backupdocument form and worked examples. - Hooks — pre/post hooks in exec and run mode, incl.
pg_dumppatterns for consistent database backups. - Backups — how backups work, consistency/snapshots, notifications.
- Restore — staging vs in-place, path mapping, database restore.
- Deployment — Compose, plain Docker, socket access, and the root/Docker-write privilege model.
- Observability — metrics, health endpoints, PromQL, dashboards, notifications.
- Architecture — how it works under the hood: the orchestrator + ephemeral mover model, discovery, per-repo serialization, and crash/shutdown behaviour.
- HTTP API — the optional, token-authenticated control API for triggering runs and browsing durable run history.
- Troubleshooting — first-response fixes for the common failures.
- FAQ — why root movers, per-app repos,
prune, bare-restic restore, Swarm.
Images¶
ghcr.io/davidborzek/sabon — a distroless image with the restic binary bundled.
Movers reuse this same image, so a plain install pulls nothing else.
ghcr.io/davidborzek/sabon/zfs-snapshotter — a small privileged image the zfs
and auto snapshot strategies pull to run the host's zfs (overridable via
SABON_SNAPSHOT_ZFS_IMAGE). Pulled only when snapshotting is enabled.