PalveronPalveronDocs

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.yaml

3. 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):

ValueDefaultNotes
gateway.image.tag / platform.image.tagchart appVersionAlways pinned — latest is rejected by the values schema
gateway.dlq.persistence.enabledtruePVC for the encrypted trace WAL (/data/dlq) — keep it on in production
gateway.nge.enabledfalseLocal ONNX analysis; needs a PVC with the models (gateway.nge.existingClaim) and ~4–5 GB RAM
redis.enabledtrueOptional in-cluster cache; the gateway degrades gracefully without Redis
gateway.mcpAllowPrivateUpstreamfalseSecurity: true disables the MCP upstream SSRF guard — only for fully isolated networks whose MCP upstreams legitimately live on private IPs
gateway.env.rustEnvproductionKeeps 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 test

Probes 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.yaml

Deployments 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.

On this page