Kubernetes

The chart's own helm/sim/README.md is the reference for every value, and goes deeper than this page on secret strategies, network policy, PII redaction, and per-error troubleshooting. This page covers the deployment path; read that alongside it.

Prerequisites

  • Kubernetes 1.25+
  • Helm 3.8+
  • PV provisioner support (a default StorageClass supporting ReadWriteOnce)
  • An ingress controller, if ingress.enabled=true
  • metrics-server, if you enable autoscaling
  • Redis — bundled by the chart (redis.enabled: true). To use your own, set app.env.REDIS_URL: a non-empty value overrides the bundled URL and suppresses its Deployment on its own. redis.enabled: false is the explicit opt-out. See Redis

Installation

The chart is published to GitHub Container Registry as an OCI artifact at oci://ghcr.io/simstudioai/charts/sim. Install it directly — no clone required.

It is also available from a classic Helm repository at https://charts.sim.ai for tooling that expects one; see Helm repository below. Prefer OCI where you can, since the signature and provenance are attached to the OCI artifact.

# Generate secrets
BETTER_AUTH_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
INTERNAL_API_SECRET=$(openssl rand -hex 32)
API_ENCRYPTION_KEY=$(openssl rand -hex 32)
CRON_SECRET=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 24)

# Install
helm install sim oci://ghcr.io/simstudioai/charts/sim \
  --version 1.9.5 \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.API_ENCRYPTION_KEY="$API_ENCRYPTION_KEY" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD" \
  --namespace simstudio --create-namespace

Save all six values somewhere durable before moving on. ENCRYPTION_KEY in particular cannot be regenerated — losing it makes workspace environment variables and stored provider keys permanently unreadable.

API_ENCRYPTION_KEY is optional, and the failure mode is silent: leave it unset and Sim stores user-generated API keys in plain text, logging one warning and nothing else. Set it at install time — it must be a 64-character hex string, which is exactly what openssl rand -hex 32 produces — and back it up like ENCRYPTION_KEY.

CRON_SECRET is required whenever background jobs are enabled, which is the chart's default: the chart will not render without it, unless it comes from app.secrets.existingSecret or External Secrets — in which case the key must be present there or every cron pod fails to start. Set cronjobs.enabled=false instead if you deliberately want no scheduled jobs.

This installs the chart's default image tag. For production, pin app, realtime, and migrations to the same explicit release tag — see Upgrades.

Helm repository

For clusters or GitOps configs that consume helm repo add rather than OCI:

helm repo add sim https://charts.sim.ai
helm repo update

helm install sim sim/sim --version 1.9.5 --namespace simstudio --create-namespace \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.API_ENCRYPTION_KEY="$API_ENCRYPTION_KEY" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD"

It serves the same chart as the OCI registry. The signature and provenance below apply to the OCI artifact only.

Verifying the chart

Every published version is signed with Sigstore keyless signing and carries a SLSA build-provenance attestation. Both live in the registry alongside the chart, so they survive a mirror into an internal registry.

cosign verify oci://ghcr.io/simstudioai/charts/sim:1.9.5 \
  --certificate-identity-regexp '^https://github.com/simstudioai/sim/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

gh attestation verify oci://ghcr.io/simstudioai/charts/sim:1.9.5 --repo simstudioai/sim

Signing is Sigstore-only — there is no GPG .prov file, so helm install --verify does not apply.

Verification requires cosign v3.0 or newer. Signatures use the Sigstore protobuf bundle format, which cosign v3 writes by default and cosign v2 cannot read. cosign v3.1+ auto-detects both formats.

Cloud-Specific Values

These are cloud-tuned alternatives to the generic install above — pick one path, don't run both. The commands reuse the $BETTER_AUTH_SECRET, $ENCRYPTION_KEY, $INTERNAL_API_SECRET, $API_ENCRYPTION_KEY, $CRON_SECRET, and $POSTGRES_PASSWORD variables generated in Installation above, so run that block's openssl lines first in the same shell. They use helm upgrade --install, so they work whether or not a release exists yet. Two caveats when converting an existing generic install rather than starting fresh: (1) reuse the original secret values — recover them with helm get values sim -n simstudio if your shell no longer has them; supplying a newly generated ENCRYPTION_KEY makes every previously encrypted value (workspace environment variables, stored provider keys, MCP OAuth credentials) undecryptable. (2) The cloud values rename the bundled PostgreSQL database to simstudio, but Postgres only applies that setting on first initialization — add --set postgresql.auth.database=sim to keep your existing database. If you'd rather start clean, helm uninstall sim -n simstudio, delete its PVCs, and run the cloud command fresh.

# The example values files are not part of the packaged chart, so fetch the one
# you want at a release tag — pinning the chart but reading values off a moving
# branch would still make this command produce different deployments over time.
SIM_RELEASE=v0.8.24
curl -fsSLO "https://raw.githubusercontent.com/simstudioai/sim/$SIM_RELEASE/helm/sim/examples/values-aws.yaml"

helm upgrade --install sim oci://ghcr.io/simstudioai/charts/sim \
  --version 1.9.5 \
  --values values-aws.yaml \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.API_ENCRYPTION_KEY="$API_ENCRYPTION_KEY" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD" \
  --set app.env.NEXT_PUBLIC_APP_URL="https://sim.yourdomain.com" \
  --set app.env.BETTER_AUTH_URL="https://sim.yourdomain.com" \
  --set app.env.NEXT_PUBLIC_SOCKET_URL="https://sim-ws.yourdomain.com" \
  --set realtime.env.ALLOWED_ORIGINS="https://sim.yourdomain.com" \
  --set ingress.app.host="sim.yourdomain.com" \
  --set ingress.realtime.host="sim-ws.yourdomain.com" \
  --namespace simstudio --create-namespace

Every one of those overrides is required. The cloud values files hardcode a placeholder domain in all six places, and overriding only NEXT_PUBLIC_APP_URL leaves sign-in pointed at the placeholder, realtime rejecting every socket upgrade, and the Ingress serving the wrong host.

Swap the --values file for your cloud: values-aws.yaml (EKS), values-azure.yaml (AKS), or values-gcp.yaml (GKE). Everything else is identical. Keep the downloaded file in your own config repo — the --set overrides above cover the six placeholder domains, but anything else you tune belongs in the file.

Key Configuration

# Custom values.yaml
app:
  replicaCount: 2
  image:
    tag: "v1.2.3"  # a tag from the releases page
  env:
    NEXT_PUBLIC_APP_URL: "https://sim.yourdomain.com"
    BETTER_AUTH_URL: "https://sim.yourdomain.com"
    OPENAI_API_KEY: "sk-..."
    # Only needed when redis.enabled is false — the bundled Redis is injected otherwise
    REDIS_URL: "redis://:<password>@redis.internal:6379"

realtime:
  image:
    tag: "v1.2.3"  # a tag from the releases page

migrations:
  image:
    tag: "v1.2.3"  # a tag from the releases page

postgresql:
  persistence:
    size: 50Gi

ingress:
  enabled: true
  className: nginx
  tls:
    enabled: true
  app:
    host: sim.yourdomain.com

NEXT_PUBLIC_APP_URL and BETTER_AUTH_URL must both be your real public origin. Leaving either at localhost breaks sign-in.

Keys set under app.env land on the realtime pod too — the chart writes them into one Secret that both Deployments consume via envFrom. Use realtime.env only for keys that must differ between the two, such as ALLOWED_ORIGINS.

The chart ships Redis (redis.enabled: true) and injects its REDIS_URL into both the app and realtime Deployments, so raising replicaCount works out of the box. The hazard is setting redis.enabled: false without supplying app.env.REDIS_URL: cross-pod events are then dropped with no error anywhere, silently breaking live collaboration and status updates. See Redis and Scaling & HA.

See helm/sim/values.yaml for all options, and the chart's README for the production checklist.

Background jobs

The chart deploys CronJobs by default, driving scheduled workflows, polling triggers, connector syncs, OAuth token cleanup, data drains, and outbox processing. They require CRON_SECRET; set cronjobs.enabled=false to deploy none.

kubectl get cronjobs -n simstudio

A CronJob with a stale LAST SCHEDULE means the corresponding feature has stopped working. See Background Jobs.

Ingress and TLS

For nginx-style ingress controllers, raise the body-size and timeout limits — Sim's defaults allow large chat attachments and long-running executions:

ingress:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "250m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"

On GKE, the load balancer's 30-second default backend timeout closes websockets and needs a BackendConfig, and the ManagedCertificate the chart references must be created by you. Both are covered in Networking.

External Database

postgresql:
  enabled: false

externalDatabase:
  enabled: true
  host: "your-db-host"
  port: 5432
  username: "postgres"
  password: "your-password"
  database: "simstudio"
  sslMode: "require"

Commands

# Port forward for local access
kubectl port-forward deployment/sim-app 3000:3000 -n simstudio

# View logs
kubectl logs -l app.kubernetes.io/component=app -n simstudio --tail=100

# Upgrade (always pin the target chart version)
helm upgrade sim oci://ghcr.io/simstudioai/charts/sim --version 1.9.5 --namespace simstudio

# Uninstall
helm uninstall sim --namespace simstudio

Common Questions

The Helm chart supports pre-existing Kubernetes secrets via app.secrets.existingSecret. Set enabled to true and provide the secret name. This integrates with External Secrets Operator, HashiCorp Vault, Azure Key Vault, and similar tools. The secret must use the standard key names (BETTER_AUTH_SECRET, ENCRYPTION_KEY, INTERNAL_API_SECRET, API_ENCRYPTION_KEY, CRON_SECRET, ...) — it is consumed wholesale, so key remapping is not supported.