Secrets

Stack relies on plain Kubernetes Secrets. Bring your own secret material and place it in the same namespace as your StackApp; the controller will not create or manage external vaults for you.

Bind secrets to services

Reference secrets through services.web.secret_env to project individual keys into environment variables:

kubectl create secret generic app-secrets \
  --namespace stack-demo \
  --from-literal=api_key=super-secret
apiVersion: stack-cli.dev/v1
kind: StackApp
metadata:
  name: stack-demo
  namespace: stack-demo
spec:
  services:
    web:
      secret_env:
        - name: API_KEY
          secret_name: app-secrets
          secret_key: api_key

Database URLs

The controller only injects database URLs when you opt in on the web service:

spec:
  services:
    web:
      database_url: DATABASE_URL
      migrations_database_url: DATABASE_MIGRATIONS_URL
      readonly_database_url: DATABASE_READONLY_URL

When working locally, you can rewrite the database URLs to point at a forwarded host/port:

stack secrets --manifest demo.stack.yaml --db-host localhost --db-port 30011

Stack-generated secrets

Use stack status to view the secrets Stack generates, including JWTs and Keycloak admin credentials:

stack status --manifest demo.stack.yaml

Example output:

🔌 Connecting to the cluster...
✅ Connected
🛡️ Keycloak Admin
   Username: temp-admin
   Password: ec74684fb30140ee994bfb5599dbbd37
☁️ Cloudflare deployment not found in namespace 'stack-demo'
🔑 JWTs
   Anon: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiJ9.E_2RkS5WSHEdZ_nxVMzTQQo-NLFLVFF8YXthl1IQk5g
   Service role: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIn0.vAnalcvp1tM4s94Qa5CHc3ZhT8_OaCmDaukhbkotcMs

Tips

  • Keep secrets small and scoped to a single app namespace.
  • Rotate secrets by updating the Kubernetes Secret; the controller will roll deployments as needed.
  • For external secret managers, sync into Kubernetes first (e.g., external-secrets) and then reference via secret_env.