Deployment
Brain Server is designed to run as a persistent, self-managed service on a single host. This page covers installing it, configuring it, keeping it healthy, and backing it up.
Service install (macOS)
scripts/install-service.sh builds the release binaries, installs them to
~/.local/bin, relocates the auth token from the launchd plist into a 0600 secret
file, restarts the service, and waits for /health. It is idempotent.
scripts/install-service.sh
This installs:
brain-server— the server (launchd-managed,KeepAlive=true,RunAtLoad=true).brain— the operator CLI (status, query, explain, ingest-dir, reconcile, resolve, backup, …).mcp— the MCP bridge (search/recall/ingest as MCP tools).bench— the latency/recall harness.brain-migrate-rehearse— migration rehearsal / recovery.brain-connector-stub(andbrain-connector-ghwhen the feature is enabled).
macOS note: newly copied executables can get a
com.apple.provenancexattr that Gatekeeper uses to SIGKILL on first exec (exit 137). The install script strips it. A manualcpdoes not.
Configuration
Brain Server is configured through environment variables (all resolved in
src/config.rs). The most important:
| Variable | Default | Description |
|---|---|---|
BIND_HOST | 127.0.0.1 | Bind address; 0.0.0.0 refused unless BIND_PUBLIC=1 |
BIND_PORT | 8765 | Listen port |
BRAIN_DB_PATH | ~/.openclaw/workspace/brain.db | SQLite database path |
CORS_ORIGINS | http://localhost:3000,http://localhost:8080 | CORS allowlist (scheme included) |
AUTH_TOKEN / AUTH_TOKEN_FILE | — | Opaque bearer token(s); newline-separated = live rotation; off if unset |
BRAIN_JWT_ISSUER | — | Enables JWT mode when set + keys loaded |
INJECTION_POLICY | quarantine | quarantine | reject | allow |
BRAIN_AUDIT_READ_EVENTS | on (JWT) / off (loopback) | Read-event audit |
BRAIN_AUDIT_RETENTION_DAYS | unset = forever | Audit retention window |
BRAIN_WEBHOOK_TIMESTAMP_REQUIRED | 0 | 1 = require the Standard Webhooks header set on /webhooks/* and verify v1, HMAC-SHA256 over {id}.{timestamp}.{body} (v1.20.4) — an opt-in hard replay window for first-party senders. GitHub sends no such timestamp; its replay protection is x-github-delivery idempotency, so the default 0 leaves the legacy sha256= path unchanged |
See Configuration and src/config.rs for the full list,
including the JWT key directory, PRF tuning, suggest kill-switch, and DSAR webhook.
Security posture in deployment
- Loopback-safe by default — refuses
0.0.0.0unlessBIND_PUBLIC=1. In addition (v1.20.29) the server fails closed on startup: a non-loopback bind with no auth configured (no bearer token, no JWT keys) refuses to start, so an unauthenticated superuser API is never exposed off the loopback. - Two auth modes:
- Opaque bearer (default):
AUTH_TOKEN/AUTH_TOKEN_FILE, constant-time compare, multiple tokens for rotation. - JWT/JWS (opt-in): set
BRAIN_JWT_ISSUER+ generate keys withbrain key generate. RS256/ES256/EdDSA only; revocation + refresh-chain reuse detection; per-route AuthZ.
- Opaque bearer (default):
- Auth token file is 0600. The install script relocates any plaintext token out of the launchd plist into the secret file.
See Security for the full model.
Health & operations
brain doctor # health + readiness
brain status # counts, model, version
brain check-consistency # duplicates, conflicts, stale sources
The audit log is read via the HTTP API (GET /audit) or the client console, not the brain
CLI (the CLI has no audit subcommand).
/health reports liveness plus a capacity object (docs / DB size / RSS) and a
hardening object (unsafe blocks, panics caught). Writes are guarded by a capacity
envelope — reads are never blocked.
Security operations runbook (v1.20.5)
Token rotation
The v1.20.2 machine-identity pattern: agents are not shared service accounts. Give each agent principal its own token and rotate on a cadence (≤90d recommended).
# opaque bearer: rotate atomically — fresh 0600 temp, fsync, rename (v1.27.12)
brain token rotate
# (or, manually: write a new token into the 0600 file; file-watch hot-reloads it)
umask 077 && head -c 32 /dev/urandom | base64 > ~/.config/brain-server/auth-token
# JWT mode: mint a fresh key, let the old one drain, then prune
brain key generate
# …wait ≥ max token lifetime (24h refresh)…
brain key prune
scripts/install-service.sh # reload the key set
brain token rotate refuses to replace a group/world-readable token file and
the server fails closed at startup on wide secret modes (token file, JWT keys,
webhook signing secret, UMP signing keys — v1.27.12). Restart the server after
rotating (scripts/install-service.sh) to load the new token.
Incident response — suspected memory poisoning
If a recall result, review item, or audit row looks planted:
- Review the blast radius —
brain check-consistency(near-dups + contradictions) +GET /decayedto see what is currently decayed. - Propose the cleanup —
GET /consolidate/proposesurfaces the duplicate / conflicting / stale-source candidates; approve the resolutions you trust. - Purge the planted rows —
POST /purgeby id/owner (hard, audited, tombstoned) orPOST /dsar {subject, action: purge}for a subject-scoped sweep. Every purge leaves a tombstone + audit row. - Re-verify the chain —
GET /audit/verify→{"ok": true}; the audit is tamper-evident, so the purge itself is provable. - Rotate tokens — steps above, so the planted session (if any) dies with the old credential.
Classifier operations (v1.20.3, layer 2)
The optional ONNX classifier is off by default; when enabled:
- FPR calibration — watch the quarantine rate (
/auditquarantinedrows; the client Security panel surfaces the flag count). TuneBRAIN_INJECTION_THRESHOLD_HIGH/LOW— policy + thresholds read per call, so a flip takes effect without a restart (only the model load is cached). - Retrain trigger — re-run adaptive evals on a threat-model shift (new obfuscation technique or delivery vector observed); the blocklist + quarantine stay the always-on defense while a retrain is pending.
- Model artifact hash-pin — pin the model file with
sha256sumin the deployment config and verify on boot; the model file is itself a supply-chain artifact (LLM04/ASI04), so it is trusted like a dependency, not like a blob.
# pin the model artifact (the gate in the feature's docs)
sha256sum /path/to/model.onnx >> models.sha256
Backup & restore
brain backup <out-path> # AES-256-GCM encrypted, checksummed, excludes secrets (DB from BRAIN_DB_PATH/default)
brain restore <in-path>
The client GUI
The Dioxus control surface (client/) runs as a web app served by the server at
/app, and as a desktop / mobile app. It gives operators a visual surface for
review, recall, security, subjects (DSAR), audit, and health.
# In the client/ directory — build the web bundle, then deploy it
./deploy-web.sh
See Client GUI.
Edge deployment (Jetson Nano / Raspberry Pi)
- Set
BRAIN_WORKER_THREADS=2to trim RSS and context-switch overhead. - The release profile is speed-optimized (
opt-level = 2) and the memory ceiling is bounded and configurable (defaultCAPACITY_MAX_RSS_MIB=512on a 4 GB ARM device; RSS is an advisory soft signal, not a hard kill). - No GPU, no embedding API, no Docker stack required.
Next steps
- Architecture — how the pieces fit together.
- Security — the full threat model.
- Compliance — regulatory mapping and data handling.