Kubernetes (Helm)
Status: Preview
Self-host Control Zero on Kubernetes via the bundled Helm chart at
charts/controlzero in the source repository. Tracks the same images
the docker-compose deployment uses; backend, gateway, and the hosted
MCP server are deployed as separate Deployments behind a single
Ingress.
The chart is v0.1.0 and supports single-namespace deployments with
bring-your-own secrets. Multi-region, mTLS between components, and
per-component HA tuning are tracked for v0.2. Talk to us at
team@controlzero.ai before running this
in production.
What ships
| Component | Purpose | Default port |
|---|---|---|
| backend | Control plane (REST API + dashboard server) | 8080 |
| gateway | LLM proxy and policy enforcement | 8000 |
| mcp-server | Hosted MCP HTTP transport (per-key isolation) | 8100 |
| relational store | Subchart (toggleable) | 5432 |
| key-value store | Subchart (toggleable) | 6379 |
| analytics store | Subchart (toggleable) | 8123 / 9000 |
Quickstart
helm dependency update ./charts/controlzero
kubectl create namespace controlzero
# Required Secrets. See "Secrets" below for the full key list.
kubectl -n controlzero create secret generic controlzero-backend-secrets \
--from-literal=SESSION_SECRET=replace-me \
--from-literal=DATABASE_URL=postgres://...
kubectl -n controlzero create secret generic controlzero-gateway-secrets \
--from-literal=CZ_GATEWAY_REDIS_URL=redis://...
helm install cz ./charts/controlzero \
--namespace controlzero \
--set global.domain=example.com
After install, helm status cz -n controlzero prints the resolved
ingress hostnames and a smoke-test command.
Bring-your-own data stores
Disable the bundled subcharts and point the apps at existing in-cluster instances:
helm install cz ./charts/controlzero \
-f ./charts/controlzero/examples/values-external-postgres.yaml \
--namespace controlzero
The example values file disables the bundled relational, key-value, and analytics stores and expects the connection URLs to live in your existing Secret.
Local smoke test (kind)
kind create cluster
helm dependency update ./charts/controlzero
kubectl create namespace controlzero
kubectl -n controlzero create secret generic controlzero-backend-secrets --from-literal=SESSION_SECRET=test
kubectl -n controlzero create secret generic controlzero-gateway-secrets --from-literal=CZ_GATEWAY_REDIS_URL=redis://cz-redis-master:6379
helm install cz ./charts/controlzero \
-f ./charts/controlzero/examples/values-kind.yaml \
--namespace controlzero
Secrets
The chart never reads sensitive values from values.yaml. Two Secrets
must exist before install:
controlzero-backend-secrets -- relational store URL, key-value
store URL, analytics store URL, session secret, and any third-party
provider keys (billing, transactional email). The full key list and
their precise environment-variable names live in
charts/controlzero/README.md
to keep this page provider-agnostic.
controlzero-gateway-secrets -- gateway key-value store URL plus
any per-provider API keys (OpenAI, Anthropic, Google, etc.) you want
the gateway to forward against. Full key list in the chart README.
Per-provider rate limits (issue #70)
flow through gateway.extraEnv in values.yaml.
Configuration reference
See charts/controlzero/values.yaml for every key. The three apps
(backend, gateway, mcpServer) each have an independent enabled
toggle, so partial deployments work (e.g., gateway-only for inference
forwarding into an existing CZ control plane elsewhere).
Upgrades
helm upgrade cz ./charts/controlzero -n controlzero
The Bitnami subcharts manage their own upgrade flows. Run
helm dependency update whenever a dependencies: version moves in
Chart.yaml.
Uninstall
helm uninstall cz -n controlzero
kubectl delete namespace controlzero # also reaps PVCs