Deploy with Docker
Docker Compose is the default way to run Obsidian. One stack brings up the API (control plane), the dashboard, and a scanner node — so you can go from clone to your first scan without wiring anything together by hand.
Prerequisites
- Docker and the Docker Compose plugin.
- Access to the Obsidian repository and images. Obsidian is in private beta — request access to get them.
Configure
Copy the example environment file:
cp .env.example .env
Set at least these two secrets in .env:
CRYPTO_DISCOVERY_CSRF_SECRET— a random value at least 32 bytes long (openssl rand -hex 32). The dashboard refuses to start without it.CRYPTO_DISCOVERY_SECRET_KEY— a base64-encoded 32-byte key (openssl rand -base64 32), used to encrypt stored secrets such as fine-grained PATs.
Start the stack
Bring up the API, dashboard, and bundled scanner node together:
docker compose --profile runner up -d --build
| Service | Role | Address |
|---|---|---|
api | Control plane and API | internal :8080 (not published) |
web | Dashboard | 127.0.0.1:3000 |
runner | Scanner node (behind the runner profile) | — |
The API pre-registers the node local-docker-runner and the runner container connects
with the matching credential, so discovery jobs run automatically. To run the platform
without a scanner node, drop the profile and use docker compose up -d --build.
The bundled
local-docker-runnercredential is a development default. For anything beyond local evaluation, issue a real node credential under Nodes and setCRYPTO_DISCOVERY_RUNNER_NODE_ID/CRYPTO_DISCOVERY_RUNNER_NODE_CREDENTIAL.
First login
Open http://localhost:3000 and go to /login. On an empty database the first visit is
the initial-admin setup, which needs a one-time token — set
CRYPTO_DISCOVERY_INITIAL_ADMIN_SETUP_TOKEN in .env, or read the generated token from
the logs:
docker compose logs api
Then add a repository (see Connect GitHub repositories) and watch the scanner node pick up the discovery job.
Production
For internet-facing deployments, run behind a reverse proxy that terminates HTTPS and add the production overlay:
docker compose -f compose.yaml -f compose.production.yaml up -d --build
The overlay enforces a production profile and drops Linux capabilities. Set
CRYPTO_DISCOVERY_SESSION_COOKIE_SECURE=true and point CRYPTO_DISCOVERY_PUBLIC_BASE_URL
at your public origin. All variables are listed in
Configuration.
Backups
All state lives in the SQLite database on the crypto-discovery-data volume. Back it up
while the stack is running:
scripts/ops/backup-sqlite.sh ./backups
Restore from a backup (this stops and restarts the API):
scripts/ops/restore-sqlite.sh ./backups/crypto-discovery-YYYYMMDDTHHMMSSZ.db
After a restore, confirm that users, nodes, scans, inventory, compliance, and audit snapshots load. Because the control plane is a single database, regular backups are your disaster-recovery path.
Upgrades
Pull the new code, rebuild, and restart:
docker compose --profile runner up -d --build
The API applies schema migrations on startup, so an upgrade is a rebuild-and-restart. Back up first, and roll forward one release at a time.
Scaling and availability
Scanner nodes scale horizontally — register more nodes to scan more repositories in parallel. The control plane and dashboard run as single instances backed by one SQLite database, so they are not horizontally scaled or highly available today: size a single host for the API and rely on backups for recovery. Built-in HA for the control plane is on the roadmap.