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
ServiceRoleAddress
apiControl plane and APIinternal :8080 (not published)
webDashboard127.0.0.1:3000
runnerScanner 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-runner credential is a development default. For anything beyond local evaluation, issue a real node credential under Nodes and set CRYPTO_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.