Deploy Mission Control¶
Mission Control supports deployment from source, reviewed release artifacts, or per-service container images. The Console and gateway share one PostgreSQL database and a reviewed YAML catalog. Managed Agents use a private Python runtime; standard OTLP uses the Collector and ClickHouse trace backend.
Choose a deployment path¶
| Your environment | Start here | You provide |
|---|---|---|
| Local development or a source evaluation | Run from source | Required runtimes, databases and service environments |
| Existing immutable-release/systemd host | Deploy to an existing VPS | The documented host layout, TLS, networking and credentials |
| Your own container platform | Container images | Orchestration, storage, TLS and mounted configuration/secrets |
Tagged releases publish signed images for gateway, Console, Agent runtime, Collector and migrations. Helm charts and cloud infrastructure modules are not included. The ClickHouse Compose fixture is a reference backend, not a complete production deployment.
An optional private ClickHouse host bootstrap prepares a resource-capped private node and the released telemetry role boundary. The bootstrap alone does not apply the Mission Control schema or start the Collector; after provisioning, follow the telemetry runbook to migrate and connect the current standard OTLP plane.
Supported topology¶
flowchart TB
Proxy[Operator-managed TLS reverse proxy]
Proxy --> Console[Console · Next.js · port 3000]
Proxy --> Gateway[Gateway · Hono · port 4000 · one or several instances]
Gateway --> Runtime[Agent runtime · PydanticAI · port 4100]
Runtime --> Gateway
External[External PydanticAI process] --> Gateway
External --> Collector[Telemetry Collector · 4317/4318]
Collector --> Gateway
Gateway --> ClickHouse[(ClickHouse metadata + permitted observations)]
Console --> ClickHouse
Console --> Database[(PostgreSQL database)]
Gateway --> Database
Console --> Mail[SMTP]
Gateway --> Catalog[Global + organization YAML]
Gateway --> Provider[Configured model providers]
Gateway --> Server[MCP Streamable HTTP server]
Use one DATABASE_URL for bootstrap, Console, gateway, the command-line tools, backup, and restore. Several gateway instances may share it behind a load balancer; Run several gateway instances gives the balancer contract and the rolling restart. The database holds governance records together with definition instructions and Chat transcripts, and must be protected as application content. The Console reaches private control through GATEWAY_MANAGEMENT_URL and inference through GATEWAY_PUBLIC_URL; browsers never call the gateway for Console Chat. External clients reach the public gateway API routes, including model discovery, Chat Completions, Responses, embeddings, reranking, MCP and deployment invoke. MCP ingress and Connector egress use only stateless revision 2026-07-28, with no legacy fallback. Browser MCP/deployment invoke origins use exact MCP_ALLOWED_ORIGINS and AGENT_ALLOWED_ORIGINS entries. Only the gateway reaches the private Agent runtime. OTLP clients reach only TLS Collector listeners; the Collector reaches signed private telemetry control/writer only, with no ClickHouse credential. Gateway owns the writer/cleanup identities.
Prerequisites¶
- Node.js
>=24 <25. - pnpm
11.22.0. - PostgreSQL 16 or newer, with a database created by the Postgres superuser with
Ccollation and owned by a dedicated login role (see Bootstrap and first sign-in), andpsql,pg_dumpandpg_restorefor backups. - Read access to the global and organization YAML files.
- SMTP for magic-link and invitation delivery outside development.
- Network routes from the gateway to configured model providers and MCP servers.
- Python
>=3.12,<3.15anduvfor the agent runtime service (required for test chat) and for the optional reference adapter, with network access from that process to the gateway. - Operator-managed TLS, ingress restrictions, egress restrictions, process supervision, and backup scheduling.
- For standard OTLP: Go
1.25.14, a supported Collector build/runtime, ClickHouse26.3.21.7for the reference contract, bounded synchronous ingestion and separate TLS/ClickHouse identities.
Install and build¶
Run from platform/:
db:migrate needs DATABASE_URL and applies the release's migrations; the gateway, the Console and connector:rotate-credentials refuse to start with STORAGE_MIGRATION_REQUIRED: run pnpm --filter @mission-control/database db:migrate until it has run. It refuses, before applying anything, a database not created with the libc C collation and character type (storage_collation_refused). The lockfile is authoritative. Do not deploy with a different Node.js major version or pnpm version; the workspace declares both in platform/package.json.
Deploy to an existing VPS¶
The existing-VPS runbook covers the repository deployment helper, its required host layout, configurable defaults, verification, and failure recovery. It applies only to an already provisioned immutable-release/systemd host.
Purpose¶
See Purpose.
Prerequisites¶
See Prerequisites.
Procedure¶
See Procedure.
Configurable defaults¶
Verification¶
See Verification.
Failure recovery¶
See Failure recovery.
Prepare durable paths¶
One example layout is:
The service account needs read access to config/ and write access to backups/. The data lives in the PostgreSQL database, not in this directory. Configuration validation resolves organization files relative to the global configuration directory and rejects organization paths that escape it.
Configure, bootstrap, and start¶
- Define the Console, split gateway, Agent runtime, Collector, and ClickHouse settings in Configure the services.
- Create the database and first owner using Bootstrap and first sign-in.
-
Start the gateway process, which binds inference and private control, from
platform/: -
Start the Collector, then start the Agent runtime from
runtime/agent-runtime/(see Configure the services): -
Start the Console from
platform/: -
Wait for Agent runtime, Collector, and Console heartbeats, then require private
http://127.0.0.1:4001/readyzto return200.
The production start commands require a successful pnpm build. Development uses each package's dev command and is not a substitute for process supervision.
Network exposure¶
- Expose the console only through authenticated TLS ingress.
- Expose public gateway routes only to intended agent/client networks.
- Do not expose private control
/healthz,/readyz, or/internal/*routes. They are operator or signed service-to-service endpoints. - Do not expose gateway telemetry-internal routes. The Collector signs them with a separate secret.
- Do not expose the Agent runtime service; keep it on loopback or a private network.
- Expose Collector OTLP listeners only through TLS to intended Agent networks; keep its health listener loopback/private.
- Keep ClickHouse native/HTTP ports private and enforce the separate insert/read/delete/backup roles.
- Restrict gateway egress to configured provider and MCP destinations.
- Set
TRUSTED_ORIGINS,MCP_ALLOWED_ORIGINS, andAGENT_ALLOWED_ORIGINSto exact externally used origins. Verify allowed and denied MCP preflights after every gateway restart; never use a wildcard. - Keep the database port private to the service hosts. Keep YAML, mail outbox, backups, and service environment outside static web roots.
Test databases for contributors¶
The package test suites and the Playwright journeys need a PostgreSQL server of their own, never the production one. From platform/, pnpm db:test:up starts a throwaway server in Docker on 127.0.0.1:5433 with durability off; pnpm db:test:down discards it. The tests read MISSION_CONTROL_TEST_DATABASE_URL (default postgres://postgres@localhost:5433/postgres) and clone one migrated template database per test; the journeys use MISSION_CONTROL_E2E_DATABASE_URL (default postgres://postgres@127.0.0.1:5433/mission_control_e2e), which they drop and recreate, and they refuse a database whose name does not contain e2e. The suites and the journeys run slower on Docker Desktop, because every statement pays a network round trip into the container: a full journey run takes about 30 minutes. See Environment variables.
Verify the deployment¶
From the private control host, require liveness/readiness:
Expected JSON is {"status":"ok"} and {"status":"ready"}. From an allowed inference host, omit a key and require the boundary to authenticate:
Expected status: 401. Then request a magic link, inspect the loaded organization catalog, allow one model in Default Team, create an ordinary virtual key, and complete a bounded model call. No Agent registration is required.
Production checklist¶
- Secrets are generated independently and stored outside the repository.
- Console and gateway use the same
DATABASE_URL, and the connection string is stored as a secret. - Console and gateway use the same
API_KEY_PEPPERandINTERNAL_SERVICE_SECRET; Collector uses internal transport asMISSION_CONTROL_INTERNAL_SERVICE_SECRET; runtime uses separate inbound/heartbeat secrets and never the gateway-only derivation master. - The database was created with
Ccollation and every migration is applied (db:migrate). - SMTP is selected; console mail is disabled by
NODE_ENV=production. - TLS and ingress/egress restrictions are active.
pg_dumpand YAML backups are scheduled and apg_restoreinto a separate database has been rehearsed.- Both processes restart automatically and preserve the durable paths.
- Private control
/healthzand/readyzare monitored without exposing them through public inference. - When enabled, Collector health, writer availability, bounded batches/retries, ClickHouse health, content scans, retention, and encrypted backup/restore are monitored and rehearsed.
- The loaded configuration and governed-call behavior are verified after restart; upstream health is diagnostic.
See Environment variables and Organization YAML. Telemetry operations documents Collector/ClickHouse deployment, backup, recovery, and rollback.