Skip to content
Select themeSelect language

Environment variables

These are the core variables read by the SupaCloud server. The standalone deployment sets them via .env (see Self-host with Docker Compose). This is a working subset, not an exhaustive list.

Variable Default Purpose
MODE dev (the default when unset) relaxes prod-only guards. Set MODE=prod (or production) for production — any other value, including unset, runs in dev mode.
PUBLIC_URL Public base URL of the server. Required in production.
CORS_ALLOWED_ORIGINS Comma-separated origins allowed to call the API.
DATABASE_URL postgresql://supacloud:supacloud@postgres:5432/supacloud PostgreSQL connection string.
SERVER_PORT 8080 Port the server listens on.
Variable Default Purpose
AUTH_PROVIDER builtin Authentication provider.
SUPACLOUD_JWT_SECRET Required. Session-signing secret, ≥ 32 bytes.
SUPACLOUD_INITIAL_ADMIN_EMAILS Email(s) provisioned as the initial owner. Required in prod for builtin/oidc (boot fails if unset); the example files ship admin@example.com only as a placeholder.
AUTH_COOKIE_SECURE false for local HTTP; true (default in prod) for HTTPS.
SECRET_BACKEND auto openbao or env. Auto-detects OpenBao when vault auth is present. See Secret provisioning.
SUPACLOUD_CALIBRATION_SWEEP_INTERVAL_SECS 86400 (1 d) How often the unattended model-chain calibration decides. The loop polls hourly and runs a pass once the last one is at least this old; the first pass comes 30 minutes after boot, 0 turns it off. With several server replicas exactly one runs each pass — the others see the lease and skip.
SUPACLOUD_CALIBRATION_SWEEP_MIN_AGE_SECS the sweep interval Minimum age of the last pass before the hourly poll runs another one. 0 means every poll, an hourly measuring mode — set it deliberately and briefly, the benchmark sources’ budgets are shared.
SUPACLOUD_CALIBRATION_REFRESH_INTERVAL_SECS 21600 (6 h) How often the benchmark source snapshots behind the calibration are refreshed. They also serve the interactive “calibrate” button, which is why they refresh faster than the sweep decides. 0 turns the refresh off.
SUPACLOUD_RESOURCE_SECRET_RECONCILE_INTERVAL_SECS 21600 (6 h) How often the server removes workflow resource secrets that no resource row will ever read again, for example after a resource create whose database write failed. Runs only with an OpenBao session; the first pass comes 15 minutes after boot; 0 turns it off. A secret is removed only after two passes found it unclaimed, not deleted and older than 15 minutes. Removal is permanent when the OpenBao policy grants delete on supacloud/metadata/workflows/resources/*; without that grant the secret is soft-deleted instead and the server logs an error.
Variable Default Purpose
GROQ_API_KEY Instance-wide Groq key (note: Groq, not Grok) used for the voice-input speech-to-text (Whisper). Set it to enable dictation across the app. Resolved env-first, then from the OpenBao supacloud/ai map when SECRET_BACKEND=openbao.
XAI_API_KEY Instance-wide xAI (Grok) API key. Backs the Grok models (grok-4.5, grok-build-0.1, …) offered through the OpenCode agent. Per-user/workspace keys are normally entered under Settings → API keys (provider xAI / Grok); this env var is the instance-wide fallback. Resolved env-first, then from the OpenBao supacloud/ai map when SECRET_BACKEND=openbao.
Variable Default Purpose
AGENT_NETWORK supacloud-agents Docker network agent containers join.
AGENT_MEMORY_BYTES 2147483648 Per-agent memory cap (bytes).
AGENT_NANO_CPUS 2000000000 Per-agent CPU cap (nano-CPUs).
AGENT_PIDS_LIMIT 512 Per-agent PID limit.
AGENT_READ_ONLY_ROOTFS true Mount the agent root filesystem read-only.
AGENT_TMPFS_TMP_MB 512 Size ceiling for the agent’s /tmp tmpfs, in MiB.
AGENT_TMPFS_RUN_MB 64 Size ceiling for the agent’s /run tmpfs, in MiB.
AGENT_TMPFS_HOME_MB 512 Size ceiling for /home/agent — the CLIs’ config/state and the npm cache.
SUPACLOUD_AGENT_TEST_DB false Wand 6 option C — instance-level CAPABILITY gate for the per-task ephemeral Postgres sidecar. With it off no sidecar is ever created. With it on, a task gets a sidecar only when it opts in (task.config.test_db = true); a non-selected task gets none. An explicit caller TEST_DATABASE_URL wins: it is never overwritten and the sidecar is suppressed. The sidecar injects TEST_DATABASE_URL, its password is registered in the run’s redaction set, and it is removed with the agent container.
AGENT_TEST_DB_IMAGE postgres:18 Image for the SUPACLOUD_AGENT_TEST_DB sidecar.
ATTACHMENTS_FILE_WAIT_MS 30000 How long an agent container waits for its attachments file. Set INSIDE the agent container, not on the server.
AGENT_TASK_TIMEOUT_MINUTES 90 Hard timeout per agent task.
MAX_PARALLEL_TASKS_PER_WORKSPACE 3 Concurrency cap per workspace.
Variable Default Purpose
SUPACLOUD_GLITCHTIP_DSN DSN of a GlitchTip (Sentry-compatible) project. When set, the server pushes targeted error events to it: operational alert breaches (tick SLA, queue age, error spike, budget 80 %, weekly window low — one event per breach onset), circuit-breaker trips / provider failover (grouped per provider and error class), and terminal workflow-run failures (with a run deep link, grouped by workflow + node + error class so a repeatedly failing interval flow stays one issue), plus error!-level log events and panics. Every payload is scrubbed by the server’s redaction wall before it leaves the process. Unset ⇒ the sink is fully disabled — no client, no network attempt. Resolved env-first, then from the OpenBao supacloud/app map.

Opt-in; off by default. See Set up a runner securely and Steer & monitor runners.

Variable Default Purpose
SUPACLOUD_HUB_MODE false Enable dispatch to remote runners. While false, every task runs locally regardless of registered runners.
SUPACLOUD_HUB_EVENT_RELAY false Relay realtime hub events across server replicas over Postgres LISTEN/NOTIFY, so a WebSocket client on any replica receives a signal emitted on another. Enable only when running multiple server replicas; a single replica is unaffected.
SUPACLOUD_RUNNER_STALE_SECS 90 Heartbeat staleness window before a runner is marked offline and its un-started work re-surfaced. Floor 45.
SUPACLOUD_TLS_CERT_PATH PEM server-certificate path. Set together with SUPACLOUD_TLS_KEY_PATH to serve the hub over TLS directly (rather than terminating TLS at a proxy). Supplying one without the other is a hard boot error (fail-closed). Unset (both) ⇒ plain HTTP exactly as today (byte-identical default).
SUPACLOUD_TLS_KEY_PATH PEM private-key path, the key half of SUPACLOUD_TLS_CERT_PATH.
SUPACLOUD_TLS_CLIENT_CA_PATH PEM CA bundle. When set (TLS must already be on) the hub additionally requires and verifies a client certificate on every connection — mutual TLS (mTLS). A runner without a trusted client cert is rejected at the handshake. Setting this without SUPACLOUD_TLS_CERT_PATH/_KEY_PATH is a hard boot error. See Set up a runner securely.

/install-runner.sh and /install-runner.ps1 are the public entry points the web wizard hands the operator. The hub does not carry the installer body: it redirects to the published, stamped installer on the release feed (runner-release.yml publishes it, version-keyed, on the public bw-public package feed). Both values are non-secret.

Variable Default Purpose
SUPACLOUD_RUNNER_VERSION Release version the hub points at: <download base>/<version>/install-runner.{sh,ps1}. Required — unset, the entry points answer 503.
SUPACLOUD_RUNNER_DOWNLOAD_BASE Base URL of the release feed, e.g. https://git.blockworx.tech/api/packages/bw-public/generic/supacloud-runner. Required — unset, the entry points answer 503.

The published, stamped installer + the release binaries come from the Forgejo release pipeline (ADR 0046), not from this server. Until the release channel is configured, onboard from the Docker image or a self-built binary.

Autoscaler (experimental, local-Docker only in v1)

Section titled “Autoscaler (experimental, local-Docker only in v1)”

Off by default. When off, no background loop is spawned and dispatch is unchanged. See Steer & monitor runners.

Variable Default Purpose
SUPACLOUD_RUNNER_AUTOSCALE off off or on. When on, the hub runs a built-in autoscaler loop that spawns and scales-in local-Docker runner containers from the fleet pull-queue signal. Default off ⇒ no loop, no behaviour change.
SUPACLOUD_RUNNER_AUTOSCALE_MIN Floor on the live runner count the autoscaler maintains.
SUPACLOUD_RUNNER_AUTOSCALE_MAX Ceiling on the runner count the autoscaler may spawn.
SUPACLOUD_RUNNER_AUTOSCALE_RUNNER_IMAGE The container image the autoscaler launches for each new runner. Required when autoscale is on. The autoscaler also needs a runner token to hand the spawned container (see the how-to).
SUPACLOUD_RUNNER_AUTOSCALE_COOLDOWN_SECS Minimum seconds between scale actions, damping flapping.
SUPACLOUD_RUNNER_AUTOSCALE_NETWORK supacloud-agents Docker network the autoscaler attaches each spawned runner container to.

On the runner (worker node, --runner mode)

Section titled “On the runner (worker node, --runner mode)”
Variable Default Purpose
SUPACLOUD_HUB_URL Required. The hub base URL. Must be https:// unless the insecure flag below is set.
SUPACLOUD_RUNNER_TOKEN The scrn_… bearer token from a system-admin registration (shown once). Provide either this or SUPACLOUD_RUNNER_ENROLLMENT_TOKEN.
SUPACLOUD_RUNNER_ENROLLMENT_TOKEN The one-time enrollment token the runner itself redeems on boot (over the gRPC ExchangeToken RPC) for a scoped, short-lived scrnj_… JWT (then auto-refreshes). Used for third-party onboarding — see Set up a runner securely. The token is single-use and consumed on first exchange; provide EITHER this OR SUPACLOUD_RUNNER_TOKEN, never both.
SUPACLOUD_RUNNER_LABELS Advertised capability labels, comma/space separated (folded lowercase + deduped). Sent as capabilities.labels at enrollment, so a task’s config.runner.required_labels can route to this runner. The runner’s backends/isolation capabilities are derived from SUPACLOUD_RUNNER_EXECUTION_BACKEND, never set here.
SUPACLOUD_RUNNER_TOKEN_FILE $XDG_STATE_HOME/supacloud-runner/runner-token (fallback $HOME/.local/state/…; %LOCALAPPDATA%\supacloud\runner-token on Windows) Path of the file the runner persists its scoped scrnj_… JWT to, and reads back on boot. The enrollment token is single-use, so without this file a reboot would leave an enrolled runner with no credential. Written atomically with mode 0600; read before any exchange, so a valid file means no second ExchangeToken. An expired, malformed, or group/world-readable file is discarded and the runner re-enrols. The installers set this explicitly (runner-token under the runner’s state directory — /var/lib/supacloud-runner as root). Ignored for a static scrn_… token, which never expires. See Set up a runner securely.
SUPACLOUD_RUNNER_TOKEN_REFRESH_SECS 0 For an enrolled (scrnj_… JWT) runner only: how many seconds before expiry to re-exchange the JWT. 0 (the default) derives the cadence automatically — roughly half the token TTL (from runners.token_expires_at / the JWT exp) — so the daemon refreshes well before the token lapses. A static scrn_… token never expires and is never refreshed; this variable is a no-op for it.
SUPACLOUD_RUNNER_NAME supacloud-runner Display name reported to the hub (unset/blank defaults to this).
SUPACLOUD_RUNNER_HEARTBEAT_SECS 30 How often the runner heartbeats the hub.
SUPACLOUD_RUNNER_POLL_SECS 3 How often the runner polls for claimable work.
SUPACLOUD_RUNNER_ALLOW_INSECURE_TRANSPORT false Permit a plaintext http:// hub URL. Only on a trusted private network — the token and per-run secrets cross this channel.
AGENT_NETWORK supacloud-agents Docker network the runner puts agent containers on (must exist on the worker).
SUPACLOUD_RUNNER_EXECUTION_BACKEND docker How the runner runs a claimed task: docker (local Docker, the default), ssh-docker (remote Docker over SSH), raw-ssh-exec (degraded, unsandboxed remote process) or microvm (strongest isolation — one launcher-spawned microVM per task). The SSH backends need a binary built with the ssh-backends feature; microvm needs one built with the microvm-backend feature. Selecting a backend whose feature was not compiled in is a hard boot error (fail-closed). See SSH execution backends and Set up a runner securely.
SUPACLOUD_RUNNER_MICROVM_CMD microvm backend only: the operator-provisioned launcher command SupaCloud invokes to start the per-task microVM (e.g. a Firecracker/Kata wrapper). Required when SUPACLOUD_RUNNER_EXECUTION_BACKEND=microvm — the runner image ships no microVM launcher.
SUPACLOUD_RUNNER_TLS_CLIENT_CERT_PATH PEM client-certificate path. Set together with SUPACLOUD_RUNNER_TLS_CLIENT_KEY_PATH so the runner presents a client identity to a hub that requires mTLS. Supplying one without the other is a hard boot error. Unset ⇒ current one-way-TLS behaviour.
SUPACLOUD_RUNNER_TLS_CLIENT_KEY_PATH PEM private-key path, the key half of SUPACLOUD_RUNNER_TLS_CLIENT_CERT_PATH.
SUPACLOUD_RUNNER_TLS_CA_PATH PEM CA bundle the runner uses to pin the hub’s certificate (rather than the system trust store). Optional; unset ⇒ current behaviour.
SUPACLOUD_SSH_HOST ssh://user@host:port — the SSH endpoint for either SSH backend. Required for ssh-docker/raw-ssh-exec.
SUPACLOUD_SSH_KNOWN_HOSTS Path to a pinned known_hosts file. Required for either SSH backend; the runner refuses to start if it is missing or empty. For raw-ssh-exec this IS the in-code anchor (russh rejects an unknown/mismatched key — no TOFU). For ssh-docker SupaCloud cannot wire it through bollard — it is only a typo-guard; you must point your system ssh client at it and set SUPACLOUD_SSH_DOCKER_HOSTKEY_DELEGATED.
SUPACLOUD_SSH_DOCKER_HOSTKEY_DELEGATED false ssh-docker only — required. Explicit acknowledgment that SSH host-key verification is delegated to the system ssh client (SupaCloud cannot enforce the pin through bollard). Selecting ssh-docker without this truthy flag is a hard boot error — otherwise an unknown host key would be silently accepted (accept-new TOFU). Set it only after configuring the runner host’s ssh with StrictHostKeyChecking=yes + UserKnownHostsFile=<SUPACLOUD_SSH_KNOWN_HOSTS>.
SUPACLOUD_SSH_KEY_PATH Path to the SSH private key file. Required for raw-ssh-exec (key auth only, no agent forwarding); optional for ssh-docker. The key bytes are never logged.
SUPACLOUD_RUNNER_ALLOW_UNSANDBOXED false GATE 1 for raw-ssh-exec. Selecting that backend without this truthy flag is a hard boot error — it runs the agent with NO container isolation and NO resource caps.
SUPACLOUD_SSH_EXEC_AGENT_CMD raw-ssh-exec only: the operator-curated remote agent-launch command template ({image}/{agent_type} placeholders, shell-quoted). Required — the work payload carries no agent entrypoint.
SUPACLOUD_SSH_INSECURE_HOST_KEY false raw-ssh-exec only: disable host-key verification (accept any server key). The only escape from fail-closed host-key checking; logs a loud warning. Never on an untrusted network.