Skip to content

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.

Get started View on GitHub

  • 🏷️ Declared next to the service


    The backup spec lives in the app's own Compose labels — not a central, disconnected config.

    Labels →

  • 📦 Per-app, per-target repos


    Each app gets isolated restic repositories, so retention and restores stay independent and the blast radius stays small.

    Backups →

  • 🔐 Incremental & encrypted


    Movers run restic: each run stores only changed data, deduplicated and client-side encrypted; a scheduled restic check verifies repository integrity.

    Backups →

  • 🗃️ Any volume driver


    Movers mount volumes by name, so named volumes (any driver) and bind mounts back up alike.

    Storage drivers →

  • 🐝 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.

    Deployment →

  • 📸 Atomic or best-effort snapshots


    snapshot: zfs backs up from a crash-consistent ZFS snapshot — no app downtime; auto snapshots what it can and mounts the rest live.

    Snapshots →

  • ♻️ Restore anywhere


    One command restores a snapshot into a staging directory or in place — even if the original app is gone.

    Restore →

  • 📊 Metrics & alerts


    Prometheus metrics, health endpoints, ready-made alert rules, and notifications catch silent failures.

    Metrics →

  • 🔌 HTTP control API


    An optional, token-authenticated API to trigger runs and browse durable run history — for dashboards and automation.

    HTTP API →

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:

docker compose exec sabon sabon backup --app paperless

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.backup document form and worked examples.
  • Hooks — pre/post hooks in exec and run mode, incl. pg_dump patterns 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.