Skip to content

Environment Variables

Use explicit absolute paths and protected secret injection. Restart the process reading an environment setting after changing it; coordinated secret or YAML activation requires matching affected services. Never place secrets in documentation, URLs or client-side bundles.

Storage and purpose-separated secrets

Variable Recipient Meaning
DATABASE_URL Console/gateway/bootstrap/command-line tools Required. postgres:// or postgresql:// URL of the one PostgreSQL 16+ database holding governance and application tables, for example postgres://mission_control:replace-with-a-generated-password@127.0.0.1:5432/mission_control. Secret; keep the password in the user part
API_KEY_PEPPER Console/gateway Key digest verification; changing it invalidates issued credentials
INTERNAL_SERVICE_SECRET Console/gateway; Collector under its prefixed name Console/Collector internal signatures only
AGENT_RUNTIME_INBOUND_SECRET Gateway/runtime Authenticate private runtime invocation
AGENT_RUNTIME_HEARTBEAT_SECRET Gateway/runtime Authenticate runtime component heartbeat
MANAGED_EXECUTION_AUTH_MASTER Gateway only Derive short-lived managed execution inference authority

The gateway requires all four transport secrets to be distinct and at least 32 characters. Runtime gets only inbound and heartbeat values, never INTERNAL_SERVICE_SECRET, the master, a caller virtual key or provider credential. Master rotation invalidates existing proofs. The Collector receives MISSION_CONTROL_INTERNAL_SERVICE_SECRET, not runtime/master secrets. Coordinate affected restarts and drain in-flight work.

DATABASE_URL changes require restarting every process that reads it. Each process opens a pool of at most 10 connections. The gateway, the Console and connector:rotate-credentials refuse to start with STORAGE_MIGRATION_REQUIRED: run pnpm --filter @mission-control/database db:migrate while a bundled migration is missing; nothing migrates at startup except bootstrap, and config:check does not check migrations. On the existing VPS the variable lives in shared.env (mode 600) and the deployment helper refuses a password= query parameter.

Test databases

These settings are for contributors' test runs only. Never point them at a server that holds real data.

Variable Default Meaning
MISSION_CONTROL_TEST_DATABASE_URL postgres://postgres@localhost:5433/postgres Administrative connection of the package test suites. Each test clones a migrated template into its own mc_test_* database and drops it afterwards. pnpm db:test:up from platform/ starts the matching throwaway server in Docker; pnpm db:test:down discards it.
MISSION_CONTROL_E2E_DATABASE_URL postgres://postgres@127.0.0.1:5433/mission_control_e2e Database the Playwright journeys drop, create, migrate and seed, then hand to the gateway and Console as DATABASE_URL. Its name must contain e2e: the journeys refuse any other database before dropping anything.

Removed in this release

The platform no longer uses these settings. Remove them from service environments and scripts.

Variable Replacement
DATABASE_PATH DATABASE_URL. The deployment helper and the service start guard refuse a shared.env that still defines it, even empty.
APPLICATION_DATABASE_PATH DATABASE_URL; the application tables live in the same database. Refused like DATABASE_PATH.
DEPLOY_DATABASE_PATH None; the deployment helper reads DATABASE_URL from shared.env. Setting it stops the helper before any Git or SSH step.
DEPLOY_APPLICATION_DATABASE_PATH None; refused like DEPLOY_DATABASE_PATH.
MISSION_CONTROL_TEST_DIALECT None; every test suite runs on Postgres.

Existing SQLite data moves once with Migrate from SQLite.

Console and authentication

Variable Default/requirement Meaning
APP_URL http://localhost:3000 Canonical Console URL for authentication/invitations.
TRUSTED_ORIGINS APP_URL Comma-separated auth origins.
BETTER_AUTH_SECRET Required runtime Session/authentication secret.
AUTH_RATE_LIMIT_MAX 20 per 60s General authentication limit.
MAGIC_LINK_RATE_LIMIT_MAX 5 per 60s Magic-link request limit.
GITHUB_CLIENT_ID Optional pair GitHub OAuth app client ID. Enables Continue with GitHub on /sign-in.
GITHUB_CLIENT_SECRET Optional pair GitHub OAuth app client secret.
BOOTSTRAP_ADMIN_EMAIL Required bootstrap First owner email and initial sign-in eligibility.
BOOTSTRAP_ORGANIZATION_NAME Required bootstrap Initial organization name.
BOOTSTRAP_ORGANIZATION_SLUG Required bootstrap Initial lowercase URL slug.
GATEWAY_PUBLIC_URL http://127.0.0.1:4000 Inference listener and Connect snippet origin; set the same value in the gateway, which derives the MCP resource identifier from it.
OAUTH_CLIENT_REDIRECT_SCHEMES Empty Comma-separated private-use URI schemes (for example cursor) accepted as client redirect URIs beside HTTPS and loopback HTTP. Empty rejects custom schemes. Changing it requires a Console restart.
GATEWAY_MANAGEMENT_URL http://127.0.0.1:4001 Private control listener used by server actions.
CONFIGURATION_REPOSITORY_URL Empty Legacy optional repository URL helper. The current Declare page provides Copy YAML without a repository shortcut; open the reviewed configuration repository separately.
CONTROL_GATEWAY_URL Falls back to management URL Console startup/30-second heartbeat destination.
CONSOLE_INSTANCE_ID Hostname/local fallback Stable Console heartbeat instance ID.
CONSOLE_INTERNAL_PORT Unset (off) Port of the Console's private health listener (/healthz). Never route it through the public ingress. Requires a Console restart.
CONSOLE_INTERNAL_HOST 127.0.0.1 Address the private health listener binds; set the pod address when an orchestrator probes it.
NEXT_PUBLIC_DOCS_URL Optional build-time Console documentation link.
NODE_ENV Runtime supplied production forbids development mail transport.

GitHub sign-in stays off until both GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET hold a value; a half-configured pair leaves the button hidden. Register the OAuth app callback as APP_URL plus /api/auth/callback/github. GitHub is a credential for an address that is already invited, so it never widens sign-in eligibility beyond BOOTSTRAP_ADMIN_EMAIL, existing accounts, and unexpired pending invitations.

Enterprise identity

These server-only settings configure one provider and one organization per Console deployment. All six required values must be set together; invalid or partial configuration prevents startup. Changes require a Console restart. See Enterprise identity.

Variable Requirement Meaning
SSO_PROVIDER Required when enabled entra, okta, or keycloak.
SSO_ORGANIZATION_SLUG Required when enabled Existing organization governed by the directory.
SSO_ISSUER Required when enabled Exact HTTPS issuer without userinfo, query or fragment.
SSO_CLIENT_ID Required when enabled Confidential OIDC application client ID.
SSO_CLIENT_SECRET Required when enabled Console-only client secret.
SCIM_BEARER_TOKEN Required when enabled Provisioning bearer secret; at least 16 characters, preferably generated with high entropy.
SSO_TENANT_ID Required for Entra only Concrete tenant GUID matching the issuer.
SSO_EXTRA_SCOPES Optional Additional space/comma-separated scopes beyond openid profile email; SCIM supplies groups.

Callbacks are /api/auth/callback/microsoft-entra-id, /api/auth/callback/okta, and /api/auth/callback/keycloak. The SCIM base is /api/scim/v2. Neither client nor SCIM secrets belong in browser settings or organization YAML. For deterministic local tests only, SSO_ALLOW_INSECURE_LOOPBACK=true permits a loopback HTTP issuer with NODE_ENV=test, or with NODE_ENV=development and MISSION_CONTROL_E2E=1. Production rejects this exception; it never allows arbitrary HTTP issuers.

Mail variables: MAIL_TRANSPORT (smtp or development-only console), MAIL_FROM, SMTP_HOST, SMTP_PORT (587), SMTP_SECURE (false), optional paired SMTP_USER/SMTP_PASSWORD, and development-only MAIL_OUTBOX_PATH.

Gateway listeners and catalog

Variable Default/requirement Meaning
MISSION_CONTROL_CONFIG ../../config/mission-control.yaml Global catalog path.
INFERENCE_GATEWAY_HOST 127.0.0.1 Public inference bind host.
INFERENCE_GATEWAY_PORT 4000 Public inference port.
CONTROL_GATEWAY_HOST 127.0.0.1 Private operations bind host.
CONTROL_GATEWAY_PORT 4001 Private operations port.
GATEWAY_DRAIN_SECONDS 10 Seconds a stopping instance keeps serving while its readiness probes answer draining, so a load balancer stops routing to it; 0 closes at once (Run several gateway instances).
GATEWAY_SHUTDOWN_TIMEOUT_SECONDS 60 After the listeners closed, seconds the requests and streams in flight may take before their connections are destroyed.
GATEWAY_MAX_IN_FLIGHT 256 Governed requests one instance admits at a time, from the end of authorization to the end of the request. Past it, requests are refused 503 instance_saturated, one Team is held to half of it (429 team_share_exceeded), and /readyz/traffic answers saturated until the instance is back under 80% (Model gateway). A positive integer; long streams at high concurrency need a higher value.
MCP_ALLOWED_ORIGINS Empty Comma-separated exact browser origins for MCP POST /mcp and OPTIONS /mcp; empty denies every browser origin, while non-browser clients may omit Origin.
APP_URL http://localhost:3000 Trusted Console URL for the MCP OAuth callback; set the same public value in Console and gateway.
GATEWAY_PUBLIC_URL http://127.0.0.1:4000 Public inference URL used to build the MCP resource identifier (<url>/mcp) and the protected-resource metadata; set it to the same value the Console uses. Changing it requires a gateway restart, and clients discover the new resource identifier at their next sign-in.
MCP_CREDENTIAL_ENCRYPTION_KEYS Required for OAuth Gateway-only JSON mapping key IDs to base64 32-byte AES keys. Retain old keys during rotation.
MCP_CREDENTIAL_ACTIVE_KEY_ID Required for OAuth Keyring entry used to encrypt client material, grants and PKCE verifiers.
MCP_AUTH_ALLOWED_PRIVATE_ORIGINS Empty Exact comma-separated HTTPS origins approved by deployment for RFC1918/ULA auth endpoints. Also requires connector origin approval; loopback/link-local/mapped addresses stay blocked.
MCP_DISCOVERY_INTERVAL_SECONDS 300 Gateway-owned unified MCP connection/schema refresh interval in seconds; 0 disables scheduled refresh. Restart gateway after changing.
AGENT_ALLOWED_ORIGINS Empty Exact browser origins for /v1/deployments/{deploymentId}:invoke.
AGENT_RUNTIME_URL http://127.0.0.1:4100 Private Agent runtime origin.
EXPERIMENTS_ENABLED true Gateway-owned evaluation experiment execution. false leaves every started experiment Queued with no item invoked, and the Console's Evaluate → Experiments pages keep working: they start, cancel and archive as usual. It also gates the judge pass: false leaves every judgment Pending, and the auto-evaluation sampler pass: false leaves every auto-evaluation unsampled, with nothing drawn from production traffic while it stands. Restart the gateway after changing it.
LOG_LEVEL info Safe/redacted service log level.
MISSION_CONTROL_OTLP_ENDPOINT Optional The Collector's /v1/traces URL for the gateway's own request spans, exported only for Organizations with telemetry.standardOtlp.enabled: true; unset disables gateway span export with a startup warning.

Every env/NAME referenced by organization YAML must exist in the gateway environment, including Anthropic/Azure API-key and model-classifier references, and must not be a reserved name.

Native cloud adapters use their SDK credential chains in the gateway. AWS uses its default chain; Azure default-credential uses DefaultAzureCredential; Vertex uses Google application default credentials. Standard SDK settings such as AWS_PROFILE, AWS workload credential variables, Azure identity variables and GOOGLE_APPLICATION_CREDENTIALS are consumed by those SDKs. Region/project/location/resource endpoints remain explicit YAML settings. See Native providers. This does not add an external secret-manager service to Mission Control.

MCP_ALLOWED_ORIGINS never accepts *. An allowed preflight must request POST and only Accept, Authorization, Content-Type, standard MCP headers, Mcp-Param-*, W3C trace headers, X-Mission-Control-Session-Id, or X-Mission-Control-Customer-Subject; every other requested header fails closed. Changing the allowlist requires a gateway restart and affects no existing key or protocol session (the current MCP revision has no sessions).

The gateway holds the writer and cleanup ClickHouse identities for the signed producer writer. It may also export its own request spans through the Collector. The Collector holds no ClickHouse credential.

Names Organization YAML cannot reference

One gateway serves every Organization, and its environment also holds the platform's own settings and secrets. A resolved reference is sent to a URL the YAML author chooses, so an env/NAME reference must name a variable that holds that Organization's own credential. These names are reserved:

Reserved for Names
Mission Control settings Every variable on this page, for any service, secret or not, and MCP_PROBE_AUTHORIZATION of the mcp:probe diagnostic command
Platform namespaces Any name starting with MISSION_CONTROL_, MC_, MCP_CREDENTIAL_, CLICKHOUSE_, AGENT_RUNTIME_, DEPLOY_, OTLP_, OTEL_, BETTER_AUTH_, NODE_ or NEXT_
AWS credential chain Any name starting with AWS_
Azure identity AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PATH, AZURE_CLIENT_CERTIFICATE_PASSWORD, AZURE_CLIENT_SEND_CERTIFICATE_CHAIN, AZURE_USERNAME, AZURE_PASSWORD, AZURE_AUTHORITY_HOST, AZURE_REGIONAL_AUTHORITY_NAME, AZURE_FEDERATED_TOKEN_FILE, AZURE_ADDITIONALLY_ALLOWED_TENANTS, AZURE_TOKEN_CREDENTIALS, AZURE_POD_IDENTITY_AUTHORITY_HOST, DEFAULT_IDENTITY_CLIENT_ID, IDENTITY_ENDPOINT, IDENTITY_HEADER, IDENTITY_SERVER_THUMBPRINT, IMDS_ENDPOINT, MSI_ENDPOINT, MSI_SECRET, and any name starting with AZURE_IDENTITY_
Google application default credentials GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_API_CERTIFICATE_CONFIG, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_QUOTA_PROJECT, GCLOUD_PROJECT, METADATA_SERVER_DETECTION, and any name starting with GOOGLE_EXTERNAL_ACCOUNT_, CLOUDSDK_ or GCE_METADATA_
PostgreSQL client PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGPASSWORD, PGPASSFILE, PGSERVICE, PGSERVICEFILE, PGOPTIONS, PGAPPNAME, PGSSLMODE, PGSSLCERT, PGSSLKEY, PGSSLROOTCERT
Outbound proxy HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY

Provider key names such as env/OPENAI_API_KEY, env/ANTHROPIC_API_KEY and env/AZURE_OPENAI_API_KEY remain available. Gateway startup, Console startup and config:check refuse a file that references a reserved name before any secret is resolved, and name the file and field:

Secret reference names a reserved platform environment variable (acme.yaml: providers.primary.credential)

To recover, set the credential in a variable the Organization owns, change the reference to that name, for example env/ACME_OPENAI_API_KEY, run config:check, and restart the gateway and Console. No new virtual key or session is needed. The gateway's secret resolver also refuses a reserved name before it reads the environment.

Agent runtime

Variable Default/requirement Meaning
AGENT_RUNTIME_HOST, AGENT_RUNTIME_PORT 127.0.0.1, 4100 Private runtime bind
MISSION_CONTROL_GATEWAY_URL Required Inference origin for scoped model/MCP work
MISSION_CONTROL_CONTROL_URL Set for heartbeat Private control origin; heartbeat secret required when set
AGENT_RUNTIME_INBOUND_SECRET Required Private invocation authentication
AGENT_RUNTIME_HEARTBEAT_SECRET Required with heartbeat Purpose-separated heartbeat authentication
MISSION_CONTROL_OTLP_ENDPOINT Required HTTP /v1/traces URL or gRPC authority
MISSION_CONTROL_OTLP_PROTOCOL http/protobuf http/protobuf or grpc
AGENT_RUNTIME_INSTANCE_ID Optional Component instance identifier
LOG_LEVEL info Safe service logging

No global secret fallback exists. Managed generation uses a 4,096 output-token bound per model round; no environment knob changes it. Reusable external clients have no global output default and must choose per-call bounds under finite budgets.

Gateway Team telemetry writer

Variable Requirement Meaning
CLICKHOUSE_URL, CLICKHOUSE_DATABASE Complete writer/admin set HTTP(S) endpoint and current Team database
CLICKHOUSE_COLLECTOR_USERNAME, CLICKHOUSE_COLLECTOR_PASSWORD Complete set Historical account name used by gateway writer, not Collector
CLICKHOUSE_ADMIN_USERNAME, CLICKHOUSE_ADMIN_PASSWORD Complete set Separate deletion/physical cleanup identity
CLICKHOUSE_TLS_CA_PATH Optional CA for gateway ClickHouse TLS

All six endpoint/database/writer/admin settings are required together. With none, observed storage is explicitly unavailable; canonical Request/ledger data is not fabricated. Partial configuration fails startup.

Console Observe reader

Variable Requirement Meaning
CLICKHOUSE_HTTP_URL All-or-none reader set Read-only HTTP(S) endpoint
CLICKHOUSE_DATABASE Reader set, mission_control Current Team database
CLICKHOUSE_USERNAME, CLICKHOUSE_PASSWORD Reader set Read-only identity, reference mission_control_repository
CLICKHOUSE_CA_FILE Optional Reader TLS CA
CLICKHOUSE_MUTATION_USERNAME, CLICKHOUSE_MUTATION_PASSWORD Optional pair Exact Team Trace deletion identity behind authorized Delete Trace observations

Absent reader settings leave canonical Requests and Usage available with explicit span-storage unavailability. Restart Console after reader/credential changes.

Collector

Variable Default/requirement Meaning
MISSION_CONTROL_INTERNAL_URL Required Private control producer authentication/writer/heartbeat origin
MISSION_CONTROL_INTERNAL_SERVICE_SECRET Required Console/Collector transport secret
OTLP_GRPC_ENDPOINT, OTLP_HTTP_ENDPOINT 127.0.0.1:4317, 127.0.0.1:4318 Trace ingress binds
OTLP_TLS_CERT_FILE, OTLP_TLS_KEY_FILE Production pair Ingress TLS
TELEMETRY_MEMORY_LIMIT_MIB, TELEMETRY_MEMORY_SPIKE_MIB 384, 64 Memory limiter and spike allowance
TELEMETRY_HEALTH_ENDPOINT 127.0.0.1:13133 Collector health-check bind address (path /health). Set 0.0.0.0:13133 in a container so the orchestrator can probe it; keep it off public networks.

The pipeline uses mc_producer and synchronous mc_writer. There are no queue-directory, native ClickHouse exporter, runtime-secret or master settings in Collector configuration. Ingress is 4 MiB; writer batches are at most 1,000 spans/4 MiB and private requests time out after five seconds.

ClickHouse migration and reference deployment

CLICKHOUSE_URL, CLICKHOUSE_MIGRATION_DATABASE, CLICKHOUSE_TLS_ENABLED, CLICKHOUSE_REQUEST_TIMEOUT_MS, CLICKHOUSE_MIGRATION_USERNAME and CLICKHOUSE_MIGRATION_PASSWORD configure migrations. Reference Compose uses CLICKHOUSE_HTTP_PORT, CLICKHOUSE_NATIVE_PORT, writer credentials above, CLICKHOUSE_REPOSITORY_USERNAME/PASSWORD, CLICKHOUSE_ADMIN_USERNAME/PASSWORD, CLICKHOUSE_BACKUP_USERNAME/PASSWORD, CLICKHOUSE_BACKUP_ENCRYPTION_KEY_HEX, OTLP_GRPC_PORT, OTLP_HTTP_PORT and TELEMETRY_HEALTH_PORT.

The current maintenance backup covers team_span_payloads, team_span_heads and team_span_deletions together. It does not use the old scoped signed-manifest API. Do not cross irreversible historical migration boundaries with a down migration.

External integrations

Variable Meaning
MISSION_CONTROL_GATEWAY_URL Inference origin
MISSION_CONTROL_API_KEY Ordinary user/service virtual key; no Agent ID
MISSION_CONTROL_VIRTUAL_MODEL Authorized generation model
MISSION_CONTROL_MCP_TOOL Declared tool for the conformance example
MISSION_CONTROL_OTLP_ENDPOINT, MISSION_CONTROL_OTLP_PROTOCOL Standard OTLP endpoint/protocol

Generic SDKs may use OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL and OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20mck_example_not_a_real_key. These authenticate export; they never grant scope through span attributes. See the PydanticAI guide.

Release version

Variable Default/requirement Meaning
MISSION_CONTROL_VERSION 0.0.0-dev The release version the gateway, Console and Agent runtime report. Release images set it from the repository's VERSION file; operators do not set it. A value that is not a semantic version, such as v0.1.0, fails startup with MISSION_CONTROL_VERSION must be a semantic version.

Deployment helper and retired setting

The VPS helper uses DEPLOY_HOST, DEPLOY_REMOTE_ROOT, DEPLOY_CONFIG_ROOT, DEPLOY_STATE_ROOT, DEPLOY_NODE_BIN_DIR, DEPLOY_UV_BIN, DEPLOY_GATEWAY_PUBLIC_URL, DEPLOY_CONSOLE_PUBLIC_URL and DEPLOY_ORGANIZATION_SLUG. It reads DATABASE_URL from shared.env on the host, validates split listener settings and never resets the database or ClickHouse. scripts/rollback_vps.sh uses the same roots and ROLLBACK_RELEASE; see Upgrade and rollback.

MCP_HEALTH_INTERVAL_SECONDS is retired and rejected at startup. Use MCP_DISCOVERY_INTERVAL_SECONDS for the single refresh schedule. Reviewed YAML/static-secret changes need coordinated gateway/Console restart; no Console Apply action exists.