Environment variables
Subspace is configured almost entirely through environment variables read at boot. There is no separate config file: set a variable before starting the server (or export it in your process manager / systemd unit) and it takes effect on the next boot. This page is the exhaustive reference; see Self-hosting for a narrative setup walkthrough.
The baseline variables every install cares about: where data lives, what port and host to bind, and which deterministic fakes to use in dev/test.
| Variable | Default | Purpose |
|---|---|---|
SUBSPACE_HOME |
~/Subspace |
Root data directory: embedded Postgres (pg/, unix socket only, no TCP) and content-addressed blobs (blobs/). Migrations run transactionally on every boot. |
SUBSPACE_PORT |
4780 |
HTTP/WebSocket port the server listens on. |
SUBSPACE_HOST |
127.0.0.1 |
Bind address. Only 127.0.0.1, localhost, or a tailnet address are legal; the server refuses to boot on a public bind (see Security and trust). |
SUBSPACE_SEED |
unset | Set to mock-world to seed the shared e2e/demo fixture (distinct inboxes, calendars, CRM rows) on first boot. |
PROVIDERS |
unset | Set to fake to swap every external seam (Jupyter kernel, search embedder, mail/calendar/IM providers, LLM calls, dev-login) for deterministic fakes. Used by tests and pnpm dev:sandbox. |
SUBSPACE_SHELL |
$SHELL |
Shell binary terminals spawn on the server host. |
SUBSPACE_AUTH |
unset | Set to off to disable identity entirely (legacy single-user behavior). The server refuses to boot with this on a non-loopback SUBSPACE_HOST. |
SUBSPACE_DEVICE_TOKEN |
unset | Bearer device token a non-browser client (desktop, mobile) stamps on every request; see Device pairing. |
SUBSPACE_MODEL |
claude-sonnet-5 |
Model id used for agent runs, event-triage classification, mail-rule matching, and other LLM seams (Vercel AI SDK + Anthropic). |
ANTHROPIC_API_KEY |
unset | Seeds the llm.anthropic capability in the capability broker on first boot (insert-only; see Tools and approvals). |
OPENAI_API_KEY |
unset | Needed for real embeddings (text-embedding-3-small) when PROVIDERS=fake is not set; also seeds the llm.openai capability. |
Backup and restore
Section titled “Backup and restore”Set any WAL-G repository variable to turn on continuous archiving; the nightly backup job and monthly restore drill pick the rest up automatically. See Backup and restore for the full lifecycle.
| Variable | Default | Purpose |
|---|---|---|
WALG_S3_PREFIX, WALG_FILE_PREFIX, WALG_GS_PREFIX, WALG_AZ_PREFIX, WALG_SSH_PREFIX, WALE_*_PREFIX |
unset | Any one of these (standard WAL-G repository variables) turns on PostgreSQL archive_command (archive_timeout=60s) and enables the 02:10 nightly backup-push job, which retains 14 full backups. |
SUBSPACE_WALG_BIN |
bundled WAL-G 3.0.8 | Dev override for the WAL-G binary path. |
SUBSPACE_BLOB_REPLICA_URL |
unset | Enables the durable blob-replicator outbox consumer: referenced blobs upload to ab/cd/<sha256> at this URL; deletes become seven-day delayed tombstones. |
SUBSPACE_BLOB_REPLICA_TOKEN |
unset | Bearer auth for SUBSPACE_BLOB_REPLICA_URL. |
RESTIC_REPOSITORY |
unset | With this set, the same nightly job snapshots okf/ (the canonical markdown dump) via restic and retains 14 daily snapshots. |
SUBSPACE_RESTIC_BIN |
restic |
Dev override for the restic binary path. |
GitOps
Section titled “GitOps”Configuring SUBSPACE_GITOPS_REPO turns on declarative config deployment
from a git repo: config pages and the plugin set sync from the repo on boot
and on a poll interval. See GitOps for the full model.
| Variable | Default | Purpose |
|---|---|---|
SUBSPACE_GITOPS_REPO |
unset | Clone URL or local path of the config repo. Setting this enables gitops sync. |
SUBSPACE_GITOPS_BRANCH |
main |
Branch to sync from. |
SUBSPACE_GITOPS_PATH |
repo root | Subdirectory within the repo holding pages/** and an optional plugins.json. |
SUBSPACE_GITOPS_POLL |
300 (seconds) |
Poll interval after the blocking boot sync; 0 means boot-only (no poll). |
SUBSPACE_GITOPS_MODE |
readonly |
Set to write-back so managed pages become editable again: every edit exports back to the repo as a commit. |
SUBSPACE_GITOPS_WRITEBACK_BRANCH |
the sync branch | In write-back mode, picks direct-to-branch commits (default) or a PR side branch. |
SUBSPACE_GITOPS_TOKEN |
unset | Seeds the gitops.git.token secret: private HTTPS remotes authenticate through GIT_ASKPASS, injected per git invocation. Absent = ambient auth (ssh-agent, credential helper). |
SUBSPACE_GITOPS_GIT_USERNAME |
x-access-token |
Overrides the basic-auth username paired with SUBSPACE_GITOPS_TOKEN. |
SUBSPACE_GITOPS_WEBHOOK_SECRET |
unset | Seeds the gitops.webhook.secret used to verify POST /gitops/webhook (GitHub/Gitea HMAC or GitLab token header). No secret configured means the webhook 403s for everyone. |
SUBSPACE_PLUGINS |
unset | Comma/space-separated npm plugin specs to reconcile at boot; a repo-pinned plugins.json (when gitops is configured) wins over this. |
Secrets and roles
Section titled “Secrets and roles”Subspace runs as a single all-in-one process by default. Opt-in posture
B splits it into a trusted web plane and a secret-scrubbed worker
plane over the same home, selected with a CLI flag rather than an env var:
subspace-server --role=web # tier 0: HTTP/WS/tRPC, Postgres, approvals, broker routessubspace-server --role=worker # tier 1: agent workflow world, scrubbed env, broker RPC onlysubspace-server --role=all # default: single process, both roles| Variable | Default | Purpose |
|---|---|---|
SUBSPACE_WORKER_URL |
:4781 |
Loopback control API the web role uses to start/resume workflows on the worker role. |
Provider and platform credentials are never read ambiently by tool code;
they seed the encrypted ops.secrets table once at boot (insert-only, a
rotated row is never clobbered by a stale env var) and are acquired through
the capability broker from then on:
| Variable | Seeds capability |
|---|---|
SLACK_BOT_TOKEN |
slack.send |
SLACK_APP_TOKEN |
slack.socket |
TELEGRAM_API_ID, TELEGRAM_API_HASH, TELEGRAM_SESSION |
telegram |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
google.oauth (also Google login) |
DEEPGRAM_API_KEY |
deepgram.stt |
ANTHROPIC_API_KEY |
llm.anthropic |
OPENAI_API_KEY |
llm.openai |
WANDB_API_KEY |
wandb.api |
DAGSTER_API_TOKEN |
dagster.api |
DEVIN_API_KEY |
devin.api |
DROPBOX_ACCESS_TOKEN |
provider.dropbox |
MICROSOFT_GRAPH_ACCESS_TOKEN, MICROSOFT_GRAPH_DRIVE_ID |
provider.sharepoint |
SUBSPACE_GITOPS_TOKEN |
gitops.git.token |
SUBSPACE_GITOPS_WEBHOOK_SECRET |
gitops.webhook.secret |
Dev and test
Section titled “Dev and test”Variables that override binaries, timings, or debug behavior. Most are only relevant when developing Subspace itself or writing e2e fixtures.
| Variable | Default | Purpose |
|---|---|---|
SUBSPACE_CLAUDE_BIN |
claude |
Overrides the Claude Code CLI binary the coding-agent dispatch ladder (code.claude.run) spawns. |
SUBSPACE_BD_BIN |
bd |
Overrides the bd issue-tracker CLI binary code.task.create shells out to. |
SUBSPACE_OS_EXEC |
unset | Set to 1 to enable the os.exec agent tool (also implicitly on under PROVIDERS=fake). |
SUBSPACE_CONTAINERS |
unset | Set to 1 to enable the real docker containers.* agent tools. |
SUBSPACE_DOCKER_BIN |
docker |
Overrides the docker binary for containers.* (e2e points this at a fixture). |
EVALS_LIVE |
unset | Set to 1 to run the eval harness against the real model instead of recorded fixtures (SUBSPACE_MODEL). See Evals. |
SUBSPACE_GRADER_MODEL |
claude-haiku-4-5 |
Model used for the cheap post-run observation grader and the weekly pattern clusterer. |
RUN_INTROSPECTION |
off |
off | observe | full (gates post-run observation grading and pattern clustering). |
SUBSPACE_INDEX_DEBOUNCE_MS |
0 under PROVIDERS=fake, 1500 otherwise |
Debounce window for the search indexer; 0 means synchronous (embed on every commit). |
SUBSPACE_MCP_SERVERS |
unset | JSON array ([{name, command, args?}], stdio) of MCP servers to bind, for names not claimed by an mcp/ page. Page-defined servers take precedence per name. See MCP servers. |
SUBSPACE_DEVIN_SWEEP_MS |
120000 (2 min) |
Poll interval for the Devin session status sweep. |
SUBSPACE_MLOPS_SWEEP_MS |
20000 (20s) |
Poll interval for the mlops run-watcher sweep. |