Skip to main content

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.

Preview release

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

ComponentPurposeDefault port
backendControl plane (REST API + dashboard server)8080
gatewayLLM proxy and policy enforcement8000
mcp-serverHosted MCP HTTP transport (per-key isolation)8100
relational storeSubchart (toggleable)5432
key-value storeSubchart (toggleable)6379
analytics storeSubchart (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