HTTP API
crucible is driven entirely over HTTP. The endpoint-by-endpoint contract is in the API reference, generated from the same OpenAPI document the daemon is tested against; this page covers the things that apply to every call.
- Base URL: whatever you pass to
--listen(defaulthttp://127.0.0.1:7878). - Content type: requests and responses are JSON, except the exec stream. Request bodies are size-capped; oversized bodies are rejected.
- Errors: any non-2xx JSON response has the shape
{"error": "message"}. - IDs are validated on every path; a malformed sandbox or snapshot ID returns
400before any work happens. - Optional subsystems answer
501when the daemon runs without them (--image-dirfor images, a service-capable rootfs,--log-dirfor logs,--app-dbfor apps). A known path with an unsupported method returns405.
Authentication
The daemon supports bearer-token API keys, on the same model as the Docker or Kubernetes CLIs.
- Loopback default: no auth. With no keys configured, the daemon (bound to
127.0.0.1) serves every request unauthenticated: the single-operator local case. - Enabling auth. Create a key with
crucible daemon token add --name <label>. The raw key is printed once (crucible_...); only its SHA-256 hash is stored. As soon as one key exists, every request must carryAuthorization: Bearer <key>or it is rejected401with aWWW-Authenticate: Bearerheader. Manage keys withcrucible daemon token list/revoke <id>; changes take effect without a daemon restart. /healthzis always exempt, so liveness probes work without a key.- Binding non-loopback requires auth plus TLS. The daemon refuses a non-loopback
--listenunless at least one key exists and--tls-cert/--tls-keyare set. Clients send the key over TLS with--token/CRUCIBLE_TOKEN.
Metrics
GET /metrics serves Prometheus metrics in the standard text format, label-free today:
| Metric | Type | Meaning |
|---|---|---|
sandboxes_created_total |
counter | Sandboxes created (cold boots + forks) |
sandboxes_active |
gauge | Sandboxes currently live |
fork_duration_seconds |
histogram | End-to-end time to bring up one fork |
snapshot_restore_duration_seconds |
histogram | Time to restore a VM from a snapshot |
Like the rest of the API, /metrics is subject to auth when keys are configured and is loopback-bound by default: scrape it from a colocated agent, not across a trust boundary.
Example session
# create
SBX=$(curl -s -XPOST localhost:7878/sandboxes -d '{"memory_mib":1024}' | jq -r .id)
# run setup
curl -s -XPOST localhost:7878/sandboxes/$SBX/exec \
-d '{"cmd":["sh","-lc","git clone https://github.com/x/y /app && cd /app && pip install -r requirements.txt"]}' --output -
# snapshot after setup
SNP=$(curl -s -XPOST localhost:7878/sandboxes/$SBX/snapshot | jq -r .id)
# fork 4 children from the warm snapshot
curl -s -XPOST "localhost:7878/snapshots/$SNP/fork?count=4" | jq '.sandboxes[].id'The exec response is a binary frame stream, specified language-neutrally in the wire protocol with conformance fixtures under sdks/fixtures. The SDKs wrap all of this.