Backup Tool v2
A self-hosted, integrity-first backup appliance for local and hardened SSH sources.
Backup Tool creates signed, content-addressed backups, supports encrypted repositories and offline recovery, and runs as isolated web, scheduler, worker, migration, and admin roles. v2.0 supports local and SSH sources, local repositories, restore, encrypted recovery, email, and signed webhooks.
What is supported
- Signed full and incremental backups, restore, retention, verification, and recovery.
- AES-256-GCM repository encryption with key epochs and offline Argon2id recovery bundles.
- Local sources and SSH sources using private-key-only, pinned-host-key, forced-SFTP chroot access.
- Durable, at-least-once webhook and STARTTLS SMTP notifications.
- A generated OpenAPI TypeScript client and operator UI.
Never use an SSH source with a shell, password, agent forwarding, remote commands, or an unchrooted account. See SSH source requirements.
Quick local verification
Prerequisites: Docker Compose, Python 3.12–3.14, Node/npm, and a working virtual environment.
make setup
make check
make test-e2e
make test-ssh-integration
make test-e2e creates temporary test-only keys and source data, starts the complete Compose stack, checks readiness/metrics/restart behavior, and tears it down. make test-ssh-integration builds a separate forced-SFTP fixture and verifies key-authenticated SSH probe, backup, verification, and restore.
Run locally with Docker Compose
The production Compose topology binds the proxy to 127.0.0.1:8080; put a TLS reverse proxy in front of it for remote access.
mkdir -p secrets sources
head -c 32 /dev/urandom > secrets/master.key
chmod 600 secrets/master.key
# The container runs as UID 10001; grant that UID read access to the key.
chown 10001:10001 secrets/master.key
# Put test source data below ./sources, then start the isolated roles.
docker compose build --pull
docker compose run --rm migrate upgrade
docker compose up -d
curl -fsS http://127.0.0.1:8080/readyz
curl -fsS http://127.0.0.1:8080/metrics
On a fresh non-loopback deployment, set BACKUP_TOOL_PUBLIC_BASE_URL to the externally reachable HTTPS URL and set BACKUP_TOOL_BOOTSTRAP_SECRET before first setup. Never expose a fresh setup endpoint without bootstrap protection.
Stop the local stack with:
docker compose down
# Add --volumes only when intentionally discarding local metadata and repositories.
Operator workflow
- Open
http://127.0.0.1:8080and create the first administrator. - Create a local or encrypted repository.
- Create a local source, or configure a hardened SSH source as documented in SSH sources.
- Create a job, run a probe, enqueue a backup, verify it, then perform a test restore.
- Configure notification subscriptions and test them before relying on delivery.
- Export and validate a recovery bundle after encrypted repository creation and each key rotation.
The browser exposes recovery status and the CLI procedure only; it never transfers recovery bundles or passphrases.
Configuration
Compose supplies the core runtime variables. The important host paths are:
| Setting | Compose value | Purpose |
|---|---|---|
BACKUP_TOOL_MASTER_KEY_FILE |
/run/backup-tool-secrets/master.key |
Service-owned 0600 master key |
BACKUP_TOOL_SOURCES_DIR |
./sources |
Read-only local-source bind mount |
BACKUP_TOOL_PUBLIC_BASE_URL |
http://localhost:8080 |
External URL and bootstrap policy |
BACKUP_TOOL_PORT |
8080 |
Loopback proxy port |
Use absolute, allowlisted paths for repositories, sources, and restores. The service rejects unsafe paths, symlinks where they violate the contract, missing key files, and non-current schemas.
Operations and security
- Observability: readiness, liveness, metrics, and alert response.
- Upgrade and rollback
- Disaster recovery
- Recovery bundles
- Repository keys
- Notifications
- SSH sources
- Security policies
Development
make setup
make test-fast
make test-integration
make test-fault
make test-security
npm --prefix frontend test -- --run
npm --prefix frontend exec playwright test
OpenAPI and the generated browser client are committed artifacts:
.venv/bin/python tools/export_openapi.py --check openapi/v2.json
npm --prefix frontend run api:generate
git diff --exit-code -- openapi/v2.json frontend/src/api/generated
Release evidence
Milestone evidence, the SBOM, provenance, and synthetic scale report live in docs/release. M15 certification is synthetic metadata certification on the reference CI host; it does not claim a physical 10 TiB transfer.
License
MIT — see LICENSE.