# 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](docs/runbooks/ssh-sources.md). ## Quick local verification Prerequisites: Docker Compose, Python 3.12–3.14, Node/npm, and a working virtual environment. ```sh 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. ```sh 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: ```sh docker compose down # Add --volumes only when intentionally discarding local metadata and repositories. ``` ## Operator workflow 1. Open `http://127.0.0.1:8080` and create the first administrator. 2. Create a local or encrypted repository. 3. Create a local source, or configure a hardened SSH source as documented in [SSH sources](docs/runbooks/ssh-sources.md). 4. Create a job, run a probe, enqueue a backup, verify it, then perform a test restore. 5. Configure notification subscriptions and test them before relying on delivery. 6. 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](docs/runbooks/observability.md): readiness, liveness, metrics, and alert response. - [Upgrade and rollback](docs/runbooks/upgrade.md) - [Disaster recovery](docs/runbooks/disaster-recovery.md) - [Recovery bundles](docs/runbooks/recovery-bundle.md) - [Repository keys](docs/runbooks/keys.md) - [Notifications](docs/runbooks/notifications.md) - [SSH sources](docs/runbooks/ssh-sources.md) - [Security policies](docs/README.md#security-boundaries) ## Development ```sh 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: ```sh .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](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](LICENSE).