Skip to main content

BackupLint logo

BackupLint

Find Docker data your backups missed before you discover it during a restore.

Don’t just assume your backups work. Prove they work.

BackupLint is an independent backup-assurance layer for Docker Compose stacks. It compares Compose mounts with your backup configuration and reports PASS, WARN, FAIL, or operational ERROR.

It is not a backup engine. It does not replace Restic, Borg, Kopia, or your backup jobs. For v1, Restic is the only supported engine when engine-backed checks are enabled. It does not SSH into hosts, delete data, or restore over live application files.

coverage ≠ integrity ≠ restore verification ≠ disaster recovery
presence (online / stale / offline) ≠ audit health
coverage FAIL ≠ repository-unavailable ERROR

Choose your deployment

BackupLint is one package. Pick a role:

Role Use it when What it does
Standalone One machine, local backup assurance only Audits this machine. No fleet controller/dashboard and does not receive other agents.
Agent This machine reports to an existing BackupLint controller Audits locally and reports over mTLS. No controller/dashboard on this machine.
Controller Dedicated central management node Receives agent reports, hosts the optional dashboard, central policy, fleet state, and optional SIEM export.
All-in-one The main server should audit itself and manage other agents Runs local checks and the fleet controller/dashboard on the same machine.
One server only → Standalone
Dedicated management server → Controller
Additional monitored servers → Agent
Main server + fleet management on one machine → All-in-one

Standalone vs all-in-one: standalone never runs a controller. All-in-one does: it is a controller that also audits the host it runs on. Use standalone unless you need a fleet.

Details: docs/installation.md, docs/installation-profiles.md.

60-second local check (standalone)

  1. Install the release wheel (see Native install).
  2. Create backuplint.yml next to your Compose file:
backup_paths:
  - /srv/docker
  - /srv/app-config
  1. Scan:
backuplint scan compose.yml
backuplint scan compose.yml --config backuplint.yml --json
BackupLint Audit

✓ sonarr       /srv/docker/sonarr    protected
✓ radarr       /srv/docker/radarr    protected
✗ vaultwarden  /srv/vaultwarden      not protected

Result: FAIL

Want fleet management?

Use controller on a management node (or all-in-one on the main server), then agent on every other host. See Choose your deployment, docs/fleet.md, and docs/dashboard.md.

What BackupLint needs from you

BackupLint does not require one broad privileged “admin account”. You supply only what each role needs.

Local audit (standalone, agent, or all-in-one)

  • Compose file path
  • BackupLint config (backuplint.yml)
  • Expected backup paths
  • Docker Engine + Compose plugin access when Compose discovery is used
  • Restic repository location for Restic-backed checks
  • Restic password via password_file, RESTIC_PASSWORD, or RESTIC_PASSWORD_FILE (password_file always wins). Passwords are never printed.

Controller

  • Hostname/DNS name agents will use (certificate SAN)
  • Listener address/port (typically 8443)
  • Controller state directory
  • Dashboard operator password if the dashboard is enabled
  • Optional SIEM endpoint/config

Agent

  • Controller URL
  • Unique agent ID from enroll-token
  • One-time enrollment token
  • Controller CA certificate
  • Local Compose/config/Restic access required for the checks that agent will run

Enrollment:

  • the agent generates its private key locally
  • the controller signs a CSR
  • the agent private key is not copied to the controller
  • the enrollment token is one-use
  • after enrollment, traffic is mTLS

Revoke with backuplint controller revoke <agent_id>.

Native / bare-metal install

Python 3.11+ (venv). Rocky/Alma 9: use python3.11. Docker Engine + Compose plugin for scan. Restic on PATH only if you enable engine-backed checks.

Download backuplint-1.0.0-py3-none-any.whl from the v1.0.0 GitHub Release, then:

python3 -m venv .venv
source .venv/bin/activate
pip install backuplint-1.0.0-py3-none-any.whl
backuplint --version

Interactive native installer (directories, optional packages, systemd):

sudo backuplint install --interactive --yes

Unattended profile:

sudo backuplint install --profile profile.yaml --non-interactive --yes

Roles, layout, CSR enrollment, upgrades, uninstall: docs/installation.md, docs/native-installer.md.

Docker install

Official GHCR images are published for linux/amd64. Raspberry Pi 4 remains a native-install current-candidate platform.

docker pull ghcr.io/netryon/backuplint-controller:1.0.0
docker pull ghcr.io/netryon/backuplint-agent:1.0.0

The same images are also tagged v1.0.0 and latest (stable 1.0.0 convenience tag). Prefer digest pinning in production; immutable digests are listed on the v1.0.0 GitHub Release.

Controller and agent images run as uid 10001. Privileged mode is not required. A Docker socket is not required for heartbeat, enrollment, or policy. Compose discovery inside an agent container needs intentional host/Docker access (not the default).

Local source builds remain available as an advanced option:

docker build -f Dockerfile.controller --build-arg BACKUPLINT_VERSION=1.0.0 -t backuplint-controller:1.0.0 .
docker build -f Dockerfile.agent --build-arg BACKUPLINT_VERSION=1.0.0 -t backuplint-agent:1.0.0 .

docs/docker.md

Dashboard

Optional read-only UI on the controller (https://…:8443/dashboard/). Presence and audit health stay separate. The dashboard does not write policy.

v1 authentication: a shared operator password, stored as a scrypt hash. There is no multi-user RBAC and no SSO in v1.

backuplint controller dashboard-password --data-dir ./bl-controller
backuplint controller run --data-dir ./bl-controller --listen 127.0.0.1:8443 --dashboard

docs/dashboard.md

Screenshots

Public-safe demo fleet (synthetic labels).

Fleet health at a glance — presence and audit state remain separate.

A healthy agent stays online with a current PASS audit.

Coverage failures and operational repository errors are reported distinctly.

Historical assurance trends from real stored audit events.

Alerts with project/service deep links.

SIEM export health is separate from backup assurance.

CLI coverage plus Restic integrity and isolated restore verification.

BackupLint failing when Vaultwarden data is missing from backups

Supported platforms (v1.0.0)

Platform Arch Current-candidate
Ubuntu x86_64 tested
Debian x86_64 tested
Rocky Linux 9 x86_64 tested
Fedora 43 x86_64 tested
Raspberry Pi 4 / Raspberry Pi OS ARM64 tested
Native controller + agent — tested
Container controller + agent, including mixed topologies — tested

Raspberry Pi 3 is not a current-candidate proof. WSL2 is unsupported.

Controller sizing is evidence-backed through 500 agents (about 6–8 MB/agent/day management-plane traffic at the tested 30s cadence). That excludes Restic backup payload. Do not treat >500 agents as certified capacity.

docs/support-matrix.md · docs/validation.md · docs/architecture.md

Security

Read-only diagnostics. No deletion of user data, no modification of backups, no secret printing from Compose, .env, or backup tools.

Container images: digest-pinned python:3.12-slim-bookworm, Trivy-reviewed, residual CVEs remain. Not a “zero CVE” claim. Agent: non-root uid 10001, unprivileged, no baked secrets.

docs/security.md · SECURITY.md

Known limitations

  • Named volume coverage depends on local docker volume inspect; missing volumes are WARN, not FAIL
  • Cache/temporary mounts are skipped by path heuristics
  • Restic coverage uses snapshot path roots, not file-level contents
  • Database image warnings are advisory; filesystem coverage is not a consistent DB backup
  • Isolated restore verification is not a disaster-recovery drill
  • Unit tests alone are not production readiness

Documentation

Topic Doc
Native install docs/installation.md
Native installer / systemd docs/native-installer.md
Docker docs/docker.md
Fleet / enrollment docs/fleet.md
Dashboard docs/dashboard.md
Troubleshooting docs/troubleshooting.md
Validation evidence docs/validation.md
Release notes docs/release-notes-v1.0.0.md

Feedback, bugs, and questions

Feedback is welcome. Please use the channel that matches what you need:

Before posting logs or configuration, remove passwords, tokens, private keys, internal hostnames/IPs, repository credentials, and personal data.

Development install

For contributors only (editable tree + test extras):

git clone https://github.com/Netryon/BackupLint.git
cd BackupLint
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
ruff check src tests
pytest -q tests/unit

See CONTRIBUTING.md.

License

MIT © 2026 BackupLint contributors.

CONTRIBUTING.md · SECURITY.md

Metadata

Release files for backuplint 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for backuplint 1.0.0
File Size Uploaded
backuplint-1.0.0.tar.gz 213.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for backuplint 1.0.0
File Interpreter ABI Platform
backuplint-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 458.3 kB

Release files / backuplint-1.0.0.tar.gz

Download URL backuplint-1.0.0.tar.gz
Size 213.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5c14a48e41f47546d5f8fe514562ea944cf0855d47843cd5bae5d1f5d4a5c218
BLAKE2b-256 checksum
How to use checksums
15ff6514ef9ca521f8b5f7e2e7fc55852b18f4d379d611641848641651f74b0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / backuplint-1.0.0-py3-none-any.whl

Download URL backuplint-1.0.0-py3-none-any.whl
Size 245.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ea11b5e3821bdf04ba262fde0678e2feb2532fdf1378b4ade722483fc03afb2
BLAKE2b-256 checksum
How to use checksums
1bb3b80d7879129ecd0d837274f86df1e9aa2063ac0f2909a628a6ff6b6d273e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page