For AI agents: the complete documentation index is available at https://docs.flezise.com/llms.txt, the full documentation bundle is available at https://docs.flezise.com/llms-full.txt, and this page is available as Markdown at https://docs.flezise.com/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

Chart layout

Each service group lives in its own directory under deploy/helm/templates/.

DirectoryWhat it deploys
backend/FastAPI API Deployment, HPA, ServiceAccount
frontend/React SPA Deployment (nginx-served)
nginx/Nginx reverse proxy: routes /api/... to the backend, /ai-gateway/ to the AI gateway, / to the frontend
workers/Celery workers (workflow-worker, generation-worker, rag-worker) and KEDA ScaledObjects
auth/Logto OIDC provider, seed Job, M2M client Secret
marketplace/Marketplace and prompt-catalog service
database/PostgreSQL StatefulSet or CNPG Cluster CR
pgbouncer/PgBouncer connection pooler (transaction mode)
redis/Redis StatefulSet
supporting/AI gateway, opensandbox controller and server, Vault utilities, headless Chrome, PlantUML, Gotenberg, injection-guard
jobs/Helm hook Jobs: db-migrate, logto-seed, library seeding; Vault bootstrap and provision (ArgoCD sync-wave)
seaweedfs/Bucket-init Job for the bundled S3-compatible store
codegraph/Code knowledge graph service
preview/Preview-environment namespace, RBAC, Ingress, and TLS Certificate
otel-collector/OpenTelemetry collector (opt-in)
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
config.llmModelclaude-sonnet-4-20250514Model name accepted by your AI gateway provider
config.agentModelanthropic/claude-opus-4-6Provider-qualified model for the builder agent
config.embeddingModelopenai/text-embedding-3-smallProvider-qualified embedding model; keep embeddingDim in sync
config.embeddingDim1536Must match the embedding model's output dimension. The pgvector column is schema-locked to this value
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.

AWS / EKS via Terraform

The Terraform stack in deploy/terraform provisions EKS, ECR, S3, EFS, and the webhook relay, then outputs a values file that wires everything together:

# 1. Apply infrastructure
cd deploy/terraform
terraform init -backend-config=backend.hcl
terraform apply -var-file=envs/cov-eval.tfvars

# 2. Push images
$(terraform output -raw ecr_login_command)
REGISTRY=$(terraform output -raw ecr_image_registry_prefix)

# 3. Deploy the chart
terraform output -raw helm_values_snippet > /tmp/aws-values.yaml
helm upgrade --install sdlc-platform deploy/helm \
  -n sdlc-platform --create-namespace \
  -f /tmp/aws-values.yaml \
  --set global.imageTag=$TAG

The helm_values_snippet output sets global.applicationImageRegistry, externalS3.* (with seaweedfs.enabled: false), IRSA annotations, the relay queue URL, gp3 for block PVCs, and efs-sc for RWX PVCs.

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