Files

120 lines
5.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.123.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).