A modern backup management application with a FastAPI backend and React frontend.
> A self-hosted, integrity-first backup appliance for local and hardened SSH sources.
## Features
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.
- **Source Type**: Local filesystem
- **Backup Strategies**: Full and incremental backups
- **Scheduled Backups**: Cron-based scheduling with APScheduler
- **Retention Policies**: Count-based and days-based backup retention
- **Web Dashboard**: React-based UI for managing backups
- **REST API**: Full REST API for programmatic access
## What is supported
## Architecture
- 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.
```
backup-tool/
├── backend/ # FastAPI backend
│ ├── app/ # FastAPI application
│ │ ├── routers/ # API endpoints
│ │ ├── models.py # SQLAlchemy models
│ │ ├── schemas.py # Pydantic schemas
│ │ └── main.py # Application entry point
│ ├── backup/ # Backup engine
│ │ ├── adapters/ # Local source adapter
│ │ ├── engine.py # Backup execution engine
│ │ ├── scheduler.py # Job scheduler
│ │ └── retention.py # Retention policies
│ └── requirements.txt # Python dependencies
├── frontend/ # React frontend
│ ├── src/ # Source code
│ └── package.json # Node dependencies
└── docs/ # Documentation
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
```
## Quick Start
`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.
### Option 1: Docker (Recommended)
## Run locally with Docker Compose
The easiest way to run the backup tool is using 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.
```bash
# Start the backend
```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
# Start with frontend (production)
docker compose --profile prod up -d
# Start with frontend (development with hot reload)
docker compose --profile dev up -d
curl -fsS http://127.0.0.1:8080/readyz
curl -fsS http://127.0.0.1:8080/metrics
```
Access the application:
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.
- Backend API: <http://localhost:8000>
- Frontend: <http://localhost:3000>
- API Docs: <http://localhost:8000/docs>
Stop the local stack with:
### Option 2: Manual Setup
#### Prerequisites
- Python 3.11+
- Node.js 18+
- PostgreSQL or MySQL (for database backups)
#### Backend Setup
```bash
cd backend
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e ".[dev]"
# Run the server
uvicorn app.main:app --reload --port 8000
```sh
docker compose down
# Add --volumes only when intentionally discarding local metadata and repositories.
```
#### Frontend Setup
## Operator workflow
```bash
cd frontend
npm install
npm run dev
```
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.
#### Production Build
```bash
cd frontend
npm run build
cd ../backend
uvicorn app.main:app --host 0.0.0.0 --port 8000
```
## API Documentation
Once the backend is running, visit:
- Swagger UI: <http://localhost:8000/docs>
- ReDoc: <http://localhost:8000/redoc>
The browser exposes recovery status and the CLI procedure only; it never transfers recovery bundles or passphrases.
## Configuration
### Environment Variables
Compose supplies the core runtime variables. The important host paths are:
| `BACKUP_TOOL_PORT` | `8080` | Loopback proxy port |
### Docker-Specific Configuration
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.
When running with Docker Compose, the following volumes are mounted:
## Operations and security
-`backup-data`: Persisted SQLite database at `/app/data`
-`backup-storage`: Backup files at `/app/backups`
### Development vs Production
**Development Mode** (`docker compose --profile dev up -d`):
-Backend hot reload enabled
- Frontend Vite dev server with HMR
- Source code mounted as volumes
**Production Mode** (`docker compose --profile prod up -d`):
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.
This index points operators and contributors to the authoritative v2.0 procedures. Do not duplicate runbook steps in release evidence or issue comments.
## Start here
- [Project quick start](../README.md)
- [Upgrade and rollback](runbooks/upgrade.md)
- [Observability and alert response](runbooks/observability.md)
- [Notification egress and delivery policy](security/notifications.md)
- SSH sources require private-key authentication, exact host-key pinning, and a forced-SFTP chrooted account. No password, shell, agent, tunnel, or remote-command mode exists.
## Release records
[Release evidence](release/) records verification rather than replacing runbooks. v2.0 scale certification is documented in `release/m15-evidence.md` and `release/m15-scale-report.json`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.