Bastion is a self-hosted backup orchestrator (Hub + optional Agents) with a Web UI.
Documentation:
- In-app (served by the Hub):
/docs/ - Source files:
docs/(EN) anddocs/zh/(ZH)
This project is early-stage. Breaking changes may occur before the first stable release.
- Hub (this repo’s main binary): HTTP API + Web UI, scheduling, metadata storage (SQLite), secrets management.
- Agent (Hub subcommand): connects to the Hub over WebSocket and executes jobs on remote nodes.
- Web UI (
ui/): Vue 3 + Vite single-page app.
- Agent labels: tag agents (e.g.,
prod,cn,db) and filter/target operations by label. Seedocs/user/agents.md. - Config sync observability: each agent shows desired/applied config snapshot state and last sync error, with “Sync now” actions. See
docs/user/agents.md. - Bulk operations: create async, per-agent operations with progress tracking + retry/cancel. See
docs/user/bulk-operations.md.- Bulk labels add/remove
- Bulk “sync config now”
- Bulk WebDAV credential distribution from Hub to agents
- Bulk deploy (clone) a job to many agents
- Job scheduling: manual/simple/cron schedules with explicit schedule timezone and overlap policy. See
docs/user/jobs.md.
- Rust
1.92+(workspacerust-version = 1.92) - Node.js
20.19+or22.12+(seeui/package.json)
cargo run -p bastionThe Hub listens on 127.0.0.1:9876 by default.
HTTPS is enforced for non-loopback traffic. For LAN/dev, either:
- keep Hub bound to loopback, or
- run with
--insecure-http, or- put it behind a reverse proxy and configure trusted proxies.
Terminal 1:
cargo run -p bastionTerminal 2:
npm ci --prefix ui
npm run dev --prefix uiOpen the UI at http://localhost:5173. The dev server proxies:
/api/*→http://127.0.0.1:9876/agent/*→http://127.0.0.1:9876(including WebSocket upgrade)/docs/*→http://127.0.0.1:9876(product docs, built output)
To build docs for the Hub (filesystem mode):
npm ci --prefix docs
npm run build --prefix docsThen open http://localhost:5173/docs/ (or use the UI "Help" button).
npm ci --prefix ui
npm run build --prefix ui
# Hub serves from ./ui/dist by default when not using embed-ui
cargo run -p bastionIf you want to serve UI assets from a different directory, set BASTION_UI_DIR (only used in filesystem mode):
BASTION_UI_DIR=/path/to/ui/dist cargo run -p bastionEmbedded mode bakes ui/dist into the Hub binary at build time.
npm ci --prefix ui
npm run build --prefix ui
cargo run -p bastion --features embed-uiOn first launch, Bastion requires initialization (create the first user). Open the UI and complete the setup flow.
Health/System endpoints (always available, even when HTTPS is enforced):
GET /api/healthGET /api/systemGET /api/setup/status
- In the Web UI, create an enrollment token (Agents page).
- Run the agent on the target machine:
bastion agent \
--hub-url http://127.0.0.1:9876 \
--enroll-token <token> \
--name "<friendly-name>"Agents store their enrollment identity in their own data directory (see BASTION_DATA_DIR).
Most settings can be configured via CLI flags or environment variables (CLI takes precedence).
Reference:
- Defaults + precedence:
docs/user/operations/defaults.md - Full CLI reference (generated):
docs/user/reference/cli.md
Common Hub options:
--host/BASTION_HOST(default127.0.0.1)--port/BASTION_PORT(default9876)--data-dir/BASTION_DATA_DIR--insecure-http/BASTION_INSECURE_HTTP(LAN/dev only)--trusted-proxy/BASTION_TRUSTED_PROXIES(repeatable / comma-separated CIDRs)
Common Agent options:
--hub-url/BASTION_HUB_URL--enroll-token/BASTION_AGENT_ENROLL_TOKEN(first-time enrollment)--name/BASTION_AGENT_NAME--data-dir/BASTION_DATA_DIR
- Bastion stores state in a data directory (SQLite + encrypted secrets). See
docs/user/operations/data-directory.md. - Use keypack export/import to back up or migrate
master.key. Seedocs/user/operations/data-directory.md. - For reverse proxy deployments (TLS termination), ensure
X-Forwarded-*headers are set and proxies are trusted. Seedocs/user/operations/reverse-proxy.md.
Run the repo’s full checks (roughly what CI runs):
bash scripts/ci.shThis repo ships optional Git hooks under .githooks/ (e.g. to prevent accidental literal \n in commit messages).
Enable locally:
git config core.hooksPath .githooksThis script includes a gitleaks secret scan step. If gitleaks is not installed, it will attempt to install a pinned version via go install (requires Go) into ~/.cache/bastion-tools/bin.
GitHub Actions CI runs the same script on pushes and pull requests (see .github/workflows/ci.yml).
- Keep user-facing changes in root
CHANGELOG.mdunder## [Unreleased]. - Use the standard categories:
Added,Changed,Deprecated,Removed,Fixed,Security. - Tag releases (
v*) must have a matching changelog section (for example## [v0.1.1] - 2026-02-12), which is used as the GitHub Release body.
Useful commands:
bash scripts/changelog.sh check
bash scripts/changelog.sh extract --tag v0.1.0 --output release-notes.md
bash scripts/release-preflight.sh --tag v0.1.0 --output release-notes.md- Product docs:
/docs/(served by the Hub; can be embedded in release builds) docs/README.md— documentation indexdocs/user/operations/data-directory.md— data directory layout + key managementdocs/user/operations/logging.md— logging configuration + rotationdocs/user/operations/reverse-proxy.md— reverse proxy examples (Nginx/Caddy)docs/user/recipes/vaultwarden.md— Vaultwarden backup recipe
Apache-2.0. See LICENSE.