Docker Compose is the fastest way to run the full Spectron stack locally. The compose file starts Spectron and SurrealDB together with a single command.
Prerequisites
Docker Desktop 4.x or later (includes Docker Compose v2)
An OpenAI or Anthropic API key for LLM operations
compose.yaml
Create a compose.yaml file in a new directory:
services:
surrealdb:
image: surrealdb/surrealdb:latest
working_dir: /data
environment:
SURREAL_PATH: rocksdb://surrealdb
command: start --log info --user root --pass secret
volumes:
- surrealdb-data:/data
ports:
- "8000:8000"
healthcheck:
test: ["CMD"
"surreal"
"isready"
"--endpoint"
"http://localhost:8000"]
interval: 5s
timeout: 5s
retries: 10
spectron:
image: ghcr.io/surrealdb/spectron:latest
depends_on:
surrealdb:
condition: service_healthy
env_file:
- .env
environment:
SPECTRON_SURREALDB_URL: ws://surrealdb:8000
SPECTRON_OBJECT_STORE_URL: file:///var/docs/spectron/objects
volumes:
- spectron-objects:/var/docs/spectron/objects
ports:
- "9090:9090"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9090/health"]
interval: 10s
timeout: 5s
retries: 5
volumes:
surrealdb-data:
spectron-objects:Storage paths
The compose file uses two different path schemes for two different systems:
| Setting | Used by | Purpose |
|---|---|---|
working_dir: /data + SURREAL_PATH: rocksdb://surrealdb | SurrealDB | On-disk database files. working_dir must match the volume mount (/data here). RocksDB creates a surrealdb directory inside that mount — not a single .db file. |
file:///var/docs/spectron/objects | Spectron (SPECTRON_OBJECT_STORE_URL) | Object store for uploaded document originals. Unrelated to SurrealDB's database path. |
Spectron connects to the running SurrealDB server over ws://surrealdb:8000 — a network client URL, not a storage path.
Troubleshooting: “read-only filesystem” or RocksDB directory errors
SurrealDB path slashes are easy to mistype. The form rocksdb://… (two slashes) is relative to working_dir. Forms like rocksdb:/… or rocksdb:///… are absolute paths on the container filesystem.
If you see Failed to create RocksDB directory or a read-only filesystem error, you may have accidentally used an absolute path (often by dropping a slash from rocksdb:// → rocksdb:/…), so SurrealDB tries to write under / instead of your mounted volume.
| Path | Meaning |
|---|---|
rocksdb://surrealdb with working_dir: /data | Database at /data/surrealdb (this compose file) |
rocksdb:/data/surrealdb | Absolute /data/surrealdb (works if /data is mounted, but easier to typo) |
rocksdb:/surrealdb | Absolute /surrealdb at filesystem root — usually fails with permission or read-only errors |
Keep working_dir and the volume mount in sync. If you change the mount from /data to something else, update working_dir to match.
See SurrealDB file-backed storage for the full path rules.
Environment file
Create a .env file alongside compose.yaml. Never commit this file to version control.
# .env
OPENAI_API_KEY=sk-...
# ANTHROPIC_API_KEY=sk-ant-... # uncomment if using Anthropic models
# Optional — allow browser clients (e.g. Surrealist) to call the user API cross-origin
# SPECTRON_CORS_ALLOWED_ORIGINS=http://localhost:1420,https://app.surrealdb.comSee Configuration — CORS for allowlist rules and management-API settings.
Starting the stack
docker compose up -dDocker pulls the images and starts both services. Wait for the health checks to pass – SurrealDB starts first, then Spectron connects to it.
Check that both services are healthy:
docker compose psNAME STATUS
spectron-1 Up (healthy)
surrealdb-1 Up (healthy)First-run initialisation
Before you can use Spectron, create an admin management key. Run this command once against the running container:
docker compose exec spectron spectron init --admin-keyThe command prints a management key secret. Copy it immediately – it is not stored in recoverable form. Store it in a secrets manager or a .env file (outside version control).
Admin key created.
Name: admin
Secret: sk_mgmt_...
This secret will not be shown again. Store it securely.Set the management key in your shell:
export SPECTRON_MGMT_KEY=sk_mgmt_...Creating your first Context
A Context is the top-level container for a Spectron deployment. Create one with the management key:
curl -s -X POST http://localhost:9090/api/v1/contexts \
-H "Authorization: Bearer $SPECTRON_MANAGEMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "dev",
"namespace": "spectron",
"database": "dev",
"config": {
"models": {
"extraction": "openai/gpt-4o-mini",
"response": "openai/gpt-4o"
}
}
}'Create an agent key for the Context:
curl -s -X POST http://localhost:9090/api/v1/contexts/dev/keys/my-agent \
-H "Authorization: Bearer $SPECTRON_MANAGEMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"principal": "agent",
"scope_floor": { "org": "my-org", "agent": "my-agent" }
}'The response includes the key secret. Use it in your application as SPECTRON_API_KEY.
Health check endpoint
curl http://localhost:9090/health{
"status": "ok",
"surrealdb": "connected",
"object_store": "ok",
"version": "0.1.0"
}A 200 OK response with "status": "ok" means Spectron is running and connected to all dependencies.
Viewing logs
# All services
docker compose logs -f
# Spectron only
docker compose logs -f spectronStopping the stack
docker compose downData persists in the named volumes (surrealdb-data, spectron-objects) and is available when you restart.
Upgrading
Pull the latest image and restart the Spectron service. Migrations run automatically at startup.
docker compose pull spectron
docker compose up -d spectronSurrealDB should be upgraded separately. Follow SurrealDB's upgrade guide before updating surrealdb/surrealdb in your compose file.
Production considerations
The configuration above is suitable for development and small internal deployments. For production, review the following before going live:
Replace
file:///var/docs/spectron/objectswith an S3 or GCS URL so object storage is not tied to the container's local filesystem.Place Spectron behind a TLS-terminating reverse proxy (Nginx, Caddy, or a cloud load balancer).
Store all secrets in a secrets manager rather than a plain
.envfile.Set
SPECTRON_MAX_UPLOAD_BYTESto match your upload policy.
See Kubernetes for a production-grade deployment guide.