For AI agents: the complete documentation index is available at https://docs.flezise.com/26.09/llms.txt, the full documentation bundle is available at https://docs.flezise.com/26.09/llms-full.txt, and this page is available as Markdown at https://docs.flezise.com/26.09/deployment/kubernetes-helm.md.

Kubernetes and Helm

The sdlc-platform Helm chart at deploy/helm deploys every platform service into one Kubernetes namespace. This page covers the chart layout, the values to set before a first install, the install command, and the post-install verification.

Prerequisites

RequirementWhy
Kubernetes clusterTarget runtime
Ingress controller with class nginxChart Ingress sets ingressClassName: nginx; the controller applies the 50 MB body limit and websocket upgrade annotations
ReadWriteMany storage classrepos, uploads, promptCache, draftStaging, opencodeSessions, and ragStorage PVCs all require RWX. Use EFS, CephFS, NFS, Longhorn with RWX enabled, or the bundled SeaweedFS CSI driver
TLS terminationEither a Secret named sdlc-tls when ingress.tls.enabled: true, or ALB/external termination with the chart Ingress on plain HTTP
CNI with NetworkPolicy enforcementOnly when networkPolicy.enabled: true. Calico, Cilium, and Weave all work
KEDA operatorOnly when keda.enabled: true and worker ScaledObjects are wanted. Set keda.install: false when the operator is already present in the cluster
CNPG operatorOnly when postgresql.cnpg.enabled: true. Replaces the in-chart PostgreSQL StatefulSet with a CloudNativePG Cluster CR
Note

The in-cluster nginx gateway routes /api/... to the backend using a location regex in deploy/helm/templates/nginx/configmap.yaml. If you add a new API path prefix, update both that file and deploy/nginx/nginx.conf or the path will not reach the backend.

Step 1: Values you must set

The chart ships with development defaults. Override these keys for every environment.

KeyDefaultSet to
global.applicationImageRegistryregistry.example.com/agentic-sweYour registry prefix
global.imageTag1.0.0Build tag pushed to the registry
ingress.hostsdlc.example.comYour platform domain
config.publicUrl""https://<ingress.host>
config.appUrl""Browser-facing origin for OAuth redirect URIs; falls back to publicUrl
logto.host(unset)Logto subdomain, e.g. auth.<domain>. Adds a separate Ingress rule so the OIDC sign-in page has a stable hostname
logto.publicUrl(unset)Browser-reachable Logto origin. The backend validates JWT iss against this value; it must be reachable from the browser, not just in-cluster
config.webhookPublicUrl""Inbound webhook endpoint; set to the relay Lambda URL when using SQS relay
dataVolumes.storageClass""A StorageClass that serves RWX. Leaving this empty takes the cluster default, which on managed clouds is a single-node block class; the second pod to want it will not schedule
secrets.postgresPassword""Strong random value (or point postgresql.auth.existingSecret at an operator-managed Secret)
secrets.internalApiKey""Strong random value (or use secrets.existingSecret)
aiGateway.adminPassword.value(unset)Strong random value (or aiGateway.adminPassword.existingSecret)
aiGateway.encryptionKey.value(unset)Strong random value. Must never change after first install. Changing it after the gateway has stored provider keys silently corrupts every stored credential

Step 2: Secrets

When vault.enabled: false, the chart generates stable Kubernetes Secrets on first install using Helm's lookup function. These secrets auto-generate if left empty:

  • PostgreSQL password (<release>-postgresql)
  • AI gateway virtual key (<release>-ai-gateway-vk; preserves the sk-bf- prefix)
  • Platform secrets (<release>-secrets): INTERNAL_API_KEY, MARKETPLACE_ADMIN_TOKEN, MARKETPLACE_RELOAD_SECRET

To supply your own, set secrets.existingSecret (and the corresponding existingSecret / secretKey triads for the AI gateway admin credential and encryption key).

When vault.enabled: true, the chart injects secrets at runtime from KV-v2 paths under secret/data/sdlc-platform/{db,api-keys,redis,s3,internal,email}.

Step 3: Install

helm dependency update deploy/helm

helm upgrade --install sdlc-platform deploy/helm \
  -n sdlc-platform --create-namespace \
  -f deploy/helm/values.yaml \
  -f deploy/helm/values-production.yaml \
  --set global.imageTag=<tag>

If a previous install is present and the Vault injector owns the webhook caBundle, pass --force-conflicts to let Helm win the field manager conflict.

Step 4: Post-install hook Jobs

Helm runs these Jobs automatically after install or upgrade:

JobWeightWhat it does
db-migrate1Runs alembic upgrade head against PostgreSQL. backoffLimit: 3, activeDeadlineSeconds: 600
logto-seed1Applies SQL patches to the Logto database
seaweedfs-bucket-init10Creates the six S3 buckets: sdlc-uploads, sdlc-repos, sdlc-rag, sdlc-projects, sdlc-staging, sdlc-packs
library-assets-seed20Downloads and seeds thumbnail assets when libraryAssets.tarballUrl is set
library-pack-seed25Downloads and seeds library packs when libraryPack.tarballUrl is set

The Vault bootstrap and provision Jobs (vault-bootstrap, vault-provision) run as ArgoCD sync-wave resources rather than Helm hooks. On a plain Helm install without ArgoCD, run them manually after the chart is up if Vault is enabled in production mode.

The logto-provisioner runs after the seed Job and creates the OIDC applications, JWT customizer, webhook, default admin account, and sign-in experience settings.

Verify

kubectl -n sdlc-platform get pods
kubectl -n sdlc-platform get jobs

All Deployments should reach Available; hook Jobs should show Succeeded. Then open the application URL and sign in with the default admin credentials from logto.provisioner.defaultAdminEmail and logto.provisioner.defaultAdminPassword (defaults: admin@sdlc.local / ChangeMe123!).

Next steps