Kubernetes (Helm)
Production-grade deployment of Palveron on Kubernetes with Helm.
The Palveron chart (oci://ghcr.io/palveron/charts/palveron) deploys the
Rust gateway and the Next.js dashboard, plus an optional in-cluster Redis
cache. It deliberately ships no PostgreSQL — bring a managed database
(Supabase recommended); the gateway applies its own schema migrations at
boot, so there is no init SQL and no migration job.
1. Create the secret
The chart never templates secret values. Create one Kubernetes Secret and reference it — these keys are mandatory (the gateway refuses to boot in production without the three encryption keys, by design):
kubectl create namespace palveron
kubectl create secret generic palveron-secrets -n palveron \
--from-literal=DATABASE_URL='postgresql://<user>:<password>@<host>:5432/<db>' \
--from-literal=PLATFORM_DATABASE_URL='postgresql://<separate-pooler-connection>' \
--from-literal=TRACE_ENCRYPTION_ROOT_KEY="$(openssl rand -base64 32)" \
--from-literal=FLARE_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
--from-literal=DLQ_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
--from-literal=PALVERON_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
--from-literal=INTERNAL_PROXY_SECRET="$(openssl rand -hex 32)" \
--from-literal=KINDE_CLIENT_SECRET='<your-kinde-client-secret>'Optional keys (feature stays off without them): OPENAI_API_KEY,
FLARE_PRIVATE_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET,
RESEND_API_KEY, OPERATOR_API_KEY, REDIS_URL (external Redis only).
Back up the three encryption keys the moment you generate them, and never
put real secrets in Git or shell history (the openssl rand pattern above
avoids both). A lost TRACE_ENCRYPTION_ROOT_KEY makes encrypted trace
content permanently unreadable — that is deliberate crypto-shredding
behavior, not a recoverable error.
2. Install
The chart is published as an OCI artifact on GHCR. Log in first (use a
GitHub token with read:packages):
helm registry login ghcr.io -u <github-user>helm install palveron oci://ghcr.io/palveron/charts/palveron --version 1.0.0 \
--namespace palveron --create-namespace \
-f my-values.yaml3. my-values.yaml
secrets:
existingSecret: palveron-secrets
gateway:
publicUrl: https://gateway.example.com # required
replicas: 2 # stateless — scale horizontally
platform:
publicUrl: https://app.example.com # required — Kinde redirects derive from it
kinde:
issuerUrl: https://yourorg.kinde.com # required — your own Kinde tenant
clientId: <kinde-client-id> # required (the SECRET lives in the Secret)
ingress:
enabled: true
className: nginx
tls:
- secretName: palveron-tls
hosts: [app.example.com, gateway.example.com]The most useful overrides (see the chart's values.yaml for the full,
commented contract):
| Value | Default | Notes |
|---|---|---|
gateway.image.tag / platform.image.tag | chart appVersion | Always pinned — latest is rejected by the values schema |
gateway.dlq.persistence.enabled | true | PVC for the encrypted trace WAL (/data/dlq) — keep it on in production |
gateway.nge.enabled | false | Local ONNX analysis; needs a PVC with the models (gateway.nge.existingClaim) and ~4–5 GB RAM |
redis.enabled | true | Optional in-cluster cache; the gateway degrades gracefully without Redis |
gateway.mcpAllowPrivateUpstream | false | Security: true disables the MCP upstream SSRF guard — only for fully isolated networks whose MCP upstreams legitimately live on private IPs |
gateway.env.rustEnv | production | Keeps the encryption boot gates armed — do not lower it for real deployments |
Missing required values fail the render with a descriptive error — if
helm install aborts with a secrets.existingSecret is required… message,
that is the chart protecting you from a boot-loop, not a bug.
Verify
kubectl -n palveron get pods
kubectl -n palveron logs deploy/palveron-gateway | grep -i migrat # boot migrations
helm test palveron -n palveron # in-cluster smoke testProbes are wired for you: the gateway's readiness gate is GET /ready
(Postgres reachable — its one hard dependency), liveness is GET /health;
the dashboard probes GET /api/health.
Upgrades
helm upgrade palveron oci://ghcr.io/palveron/charts/palveron --version <new> \
-n palveron -f my-values.yamlDeployments use rolling updates; the gateway is stateless (the DLQ PVC and
your database carry all state), so upgrades do not interrupt traffic with
replicas: 2+.
Known limitation — dashboard public URLs. The platform image bakes
NEXT_PUBLIC_* values at build time. Self-hosting under your own domain
requires rebuilding the platform image with your
NEXT_PUBLIC_PALVERON_CORE_URL (see Dockerfile.platform build args in
the platform repo). Server-side calls already use in-cluster Service DNS
and need no rebuild.
For single-server setups without Kubernetes, see the Docker Compose guide.