Skip to main content

Overview

The CrewAI Platform Helm chart provides a production-ready deployment with:
  • PostgreSQL database (internal StatefulSet or external)
  • MinIO object storage (optional S3-compatible storage)
  • Background workers (Rails ActiveJob for async processing)
  • Web application (Rails-based with flexible ingress support)
  • Intelligent secret management with auto-population from Replicated license fields
  • Multi-provider ingress support (AWS ALB, NGINX, Istio)
  • BuildKit service for container image building

Quick Start for Production

Minimum Required Configuration

For a production deployment with external database and S3 storage:
my-values.yaml
# Production-ready configuration
image:
  tag: latest # Use specific version tag in production

# Configure external database
envVars:
  DB_HOST: "your-postgres-host.amazonaws.com"
  DB_PORT: "5432"
  DB_USER: "crewai"
  POSTGRES_DB: "crewai_plus_production"
  POSTGRES_CABLE_DB: "crewai_plus_cable_production"

  # S3 configuration
  STORAGE_SERVICE: "amazon"
  AWS_REGION: "us-west-2"
  AWS_BUCKET: "your-crewai-bucket"

  # Application hostname
  APPLICATION_HOST: "crewai.your-company.com"

  # Authentication provider
  AUTH_PROVIDER: "local" # or "entra_id", "okta", "workos"

# Provide secrets
secrets:
  DB_PASSWORD: "your-secure-password"
  AWS_ACCESS_KEY_ID: "your-aws-access-key"
  AWS_SECRET_ACCESS_KEY: "your-aws-secret-key"

# Configure ingress
web:
  ingress:
    enabled: true
    className: nginx
    host: "crewai.your-company.com"
    nginx:
      tls:
        enabled: true
        secretName: "crewai-tls-secret"

Critical Production Configuration Areas

1. Database Configuration

For External PostgreSQL (Recommended):
postgres:
  enabled: false # Do not create internal PostgreSQL

envVars:
  DB_HOST: "your-postgres-host.amazonaws.com"
  DB_PORT: "5432"
  DB_USER: "crewai"
  POSTGRES_DB: "crewai_plus_production"
  POSTGRES_CABLE_DB: "crewai_plus_cable_production"

secrets:
  DB_PASSWORD: "your-secure-password"
The internal PostgreSQL option (postgres.enabled: true) is not intended for production use. It lacks high-availability features, automated backups, and enterprise-grade reliability. Always use an external managed PostgreSQL service (AWS RDS, Azure Database, Google Cloud SQL, etc.) for production deployments.
Internal PostgreSQL (Development/Testing Only):
postgres:
  enabled: true
  persistence:
    size: 20Gi
    storageClassName: "your-storage-class"
  resources:
    limits:
      cpu: "2"
      memory: "4Gi"

2. Object Storage Configuration

For External S3 (Recommended):
minio:
  enabled: false # Disable internal MinIO

envVars:
  STORAGE_SERVICE: "amazon" # or "microsoft" for Azure
  AWS_REGION: "us-west-2"
  AWS_BUCKET: "your-crewai-bucket"
  # For S3-compatible services:
  # AWS_ENDPOINT: "https://s3.your-provider.com"

secrets:
  AWS_ACCESS_KEY_ID: "your-access-key"
  AWS_SECRET_ACCESS_KEY: "your-secret-key"
For Azure Blob Storage:
envVars:
  STORAGE_SERVICE: "microsoft"
  AZURE_STORAGE_ACCOUNT_NAME: "youraccountname"

secrets:
  AZURE_STORAGE_ACCESS_KEY: "your-azure-key"
The internal MinIO option (minio.enabled: true) is not intended for production use. Use external S3-compatible storage for production deployments.

3. Secret Management

The chart supports three secret management approaches:

Option A: Direct Secret Values (Simple)

secrets:
  DB_PASSWORD: "your-db-password"
  AWS_ACCESS_KEY_ID: "your-aws-key"
  AWS_SECRET_ACCESS_KEY: "your-aws-secret"
  # Other secrets...
Secrets are base64-encoded automatically. Some secrets like SECRET_KEY_BASE are auto-generated with upgrade persistence using the lookup function if not provided.
# Enable external secret store integration
externalSecret:
  enabled: true
  secretStore: "crewai-secret-store"
  secretPath: "crewai/platform"
  databaseSecretPath: "crewai/database"
  includes_aws_credentials: true
  includes_azure_credentials: false

# Configure AWS Secrets Manager
secretStore:
  enabled: true
  provider: "aws"
  aws:
    region: "us-west-2"
    role: "arn:aws:iam::ACCOUNT:role/crewai-secrets-role"
    auth:
      serviceAccount:
        enabled: true
        name: "crewai-secret-reader"

4. Ingress and Networking

AWS Application Load Balancer

web:
  ingress:
    enabled: true
    className: "alb"
    host: "crewai.your-company.com"
    alb:
      scheme: "internet-facing"
      targetType: "ip"
      certificateArn: "arn:aws:acm:us-west-2:ACCOUNT:certificate/CERT-ID"
      sslPolicy: "ELBSecurityPolicy-TLS-1-2-2017-01"

NGINX Ingress Controller

web:
  ingress:
    enabled: true
    className: "nginx"
    host: "crewai.your-company.com"
    nginx:
      sslRedirect: true
      tls:
        enabled: true
        secretName: "crewai-tls-secret"
      enableCors: true
      sessionAffinity: true
      whitelistSourceRange: "10.0.0.0/8,172.16.0.0/12"

Application-Level TLS (Self-Signed)

For environments without ingress TLS, enable application-level HTTPS:
web:
  useHttps: true
  service:
    type: LoadBalancer
  tls:
    autoGenerate: true # Generates self-signed certificate
    duration: 365 # Certificate validity in days
    hosts:
      - localhost
      - crewai.internal

5. Authentication Configuration

Local Authentication

envVars:
  AUTH_PROVIDER: "local"

Microsoft Entra ID (Azure AD)

envVars:
  AUTH_PROVIDER: "entra_id"

secrets:
  # Required for Entra ID authentication
  ENTRA_ID_CLIENT_ID: "your-application-client-id"
  ENTRA_ID_TENANT_ID: "your-tenant-id"
  ENTRA_ID_CLIENT_SECRET: "your-client-secret"
Setup Steps:
  1. Register an application in Azure Active Directory
  2. Configure redirect URIs: https://your-domain/auth/entra_id/callback
  3. Generate a client secret in the app registration
  4. Note the Application (client) ID and Directory (tenant) ID

Okta

envVars:
  AUTH_PROVIDER: "okta"

secrets:
  # Required for Okta authentication
  OKTA_SITE: "https://your-domain.okta.com"
  OKTA_CLIENT_ID: "your-okta-client-id"
  OKTA_AUTHORIZATION_SERVER: "default" # or your custom authorization server ID
  OKTA_AUDIENCE: "api://default" # or your custom audience
Setup Steps:
  1. Create an application integration in Okta Admin Console
  2. Choose “OIDC - OpenID Connect” as the sign-in method
  3. Select “Web Application” as the application type
  4. Configure Sign-in redirect URIs: https://your-domain/auth/okta/callback
  5. Note the Client ID and configure the authorization server

WorkOS

envVars:
  AUTH_PROVIDER: "workos"

secrets:
  # Required for WorkOS authentication
  WORKOS_CLIENT_ID: "your-workos-client-id"
  WORKOS_AUTHKIT_DOMAIN: "your-authkit-domain.authkit.com"
Setup Steps:
  1. Create a new application in WorkOS Dashboard
  2. Configure the redirect URI: https://your-domain/auth/workos/callback
  3. Note the Client ID from the application configuration
  4. Configure your AuthKit domain

6. Resource Sizing

Production-grade resource defaults are included, but adjust based on your workload:
web:
  replicaCount: 2 # Increase for high availability
  resources:
    limits:
      cpu: "6"
      memory: "12Gi"
    requests:
      cpu: "1000m" # Increase for production
      memory: "6Gi"

worker:
  replicaCount: 2 # Increase based on job volume
  resources:
    limits:
      cpu: "6"
      memory: "12Gi"
    requests:
      cpu: "1000m"
      memory: "6Gi"

buildkit:
  enabled: true
  replicaCount: 1
  resources:
    limits:
      cpu: "4"
      memory: "8Gi"
    requests:
      cpu: "500m"
      memory: "2Gi"
The default resource requests are conservative. For production workloads, increase requests to ensure reliable scheduling and performance.

7. High Availability Configuration

For production HA deployments:
web:
  replicaCount: 3  # Multiple replicas for zero-downtime
  terminationGracePeriodSeconds: 60  # Allow graceful shutdown

worker:
  replicaCount: 3  # Distribute background job processing

# Use external, HA-enabled services
postgres:
  enabled: false  # Use AWS RDS Multi-AZ or similar

minio:
  enabled: false  # Use S3 or similar

# Configure node placement for multi-AZ
web:
  nodeSelector:
    topology.kubernetes.io/zone: us-west-2a

worker:
  nodeSelector:
    topology.kubernetes.io/zone: us-west-2b

8. Image Registry Configuration

Using Replicated Proxy (Default)

image:
  host: "images.crewai.com"
  name: "proxy/crewai/crewai/crewai-enterprise-platform"
  tag: "latest"
  pullPolicy: Always
  pullSecret: "docker-registry" # Automatically created by Replicated

Private Registry with Simplified Paths

When mirroring images to a private registry like AWS ECR or Azure ACR, use global.imageNamePrefixOverride to simplify image paths:
global:
  imageRegistry: "123456789012.dkr.ecr.us-west-2.amazonaws.com"
  imageNamePrefixOverride: "crewai/"

image:
  registries:
    - host: "123456789012.dkr.ecr.us-west-2.amazonaws.com"
      credHelper: "ecr-login"

envVars:
  CREW_IMAGE_REGISTRY_OVERRIDE: "123456789012.dkr.ecr.us-west-2.amazonaws.com"
How it works:
  • Without override: images.crewai.com/proxy/crewai/dockerhub/library/postgres:16
  • With override: 123456789012.dkr.ecr.us-west-2.amazonaws.com/crewai/postgres:16
The imageNamePrefixOverride replaces complex multi-level paths (like proxy/crewai/dockerhub/library/) with a simple prefix. It extracts only the final image name component (e.g., postgres) and applies the override prefix to it. This is not a simple prepend operation - it completely replaces the path structure, making image management in private registries easier. Affected components:
  • Main application, PostgreSQL, MinIO, BuildKit, Redis, Busybox images
  • Environment variables: CONTAINER_REGISTRY_HOSTNAME, AUTOMATION_ECR_REPOSITORY_PREFIX
Complete Example:
global:
  imageRegistry: "123456789012.dkr.ecr.us-west-2.amazonaws.com"
  imageNamePrefixOverride: "crewai/"

image:
  registries:
    - host: "123456789012.dkr.ecr.us-west-2.amazonaws.com"
      credHelper: "ecr-login"

envVars:
  CREW_IMAGE_REGISTRY_OVERRIDE: "123456789012.dkr.ecr.us-west-2.amazonaws.com"

Additional Private Registries

image:
  registries:
    - host: "your-registry.company.com"
      username: "registry-user"
      password: "registry-password"
    - host: "docker.io"
      username: "dockerhub-user"
      password: "dockerhub-token"

Security Best Practices

1. Secret Management

  • Never commit secrets to version control
  • Use external secret stores (AWS Secrets Manager, Azure Key Vault) for production
  • Rotate secrets regularly

2. Network Security

  • Enable TLS for all external endpoints
  • Configure ingress whitelist restrictions
  • Use private subnets for database and internal services
  • Enable CORS with restrictive origin policies

3. RBAC and Service Accounts

rbac:
  create: true # Creates necessary service accounts and role bindings

serviceAccount: "crewai-platform" # Custom service account name

4. Database Security

  • Use encrypted connections to database (SSL/TLS)
  • Store database credentials in secret stores
  • Enable audit logging on database

5. Database Migration Management

The chart implements automatic database migrations via Helm hooks, ensuring schema changes and data migrations are applied safely during installation and upgrades. Migration Process: During Initial Installation (helm install):
  1. After deployment, a setup Job runs automatically
  2. Job waits for PostgreSQL and MinIO availability (when enabled)
  3. Executes rails db:migrate for main database
  4. Executes rails db:migrate:cable for ActionCable database
  5. Executes rails db:seed to populate initial data
  6. Executes rake data:migrate to apply data migrations
  7. Sets up default permissions and syncs feature flags
  8. Job retries up to 10 times on failure
During Upgrades (helm upgrade):
  1. Before each upgrade, a pre-upgrade Job runs automatically
  2. Job waits for PostgreSQL availability (when using internal PostgreSQL)
  3. Executes rails db:migrate for main database
  4. Executes rails db:migrate:cable for ActionCable database
  5. Executes rake data:migrate to apply data migrations
  6. Job retries up to 3 times on failure
  7. Upgrade proceeds only after successful migration
Data migrations (rake data:migrate) are automatically applied during both initial installation and upgrades, ensuring data transformations are kept in sync with schema changes.
Custom Node Placement:
# For initial setup job
setupJob:
  nodeSelector:
    node-role.kubernetes.io/worker: "true"

# For pre-upgrade migration job
migrationJob:
  nodeSelector:
    node-role.kubernetes.io/worker: "true"
Troubleshooting: View migration job logs:
# For upgrades
kubectl logs -l app.kubernetes.io/component=migration --tail=100

# For initial setup
kubectl logs -l app.kubernetes.io/component=setup --tail=100
Check migration job status:
# For upgrades
kubectl get jobs -l app.kubernetes.io/component=migration

# For initial setup
kubectl get jobs -l app.kubernetes.io/component=setup

Common Deployment Scenarios

Scenario 1: AWS Production Deployment

postgres:
  enabled: false

minio:
  enabled: false

envVars:
  DB_HOST: "crewai-prod.cluster-xyz.us-west-2.rds.amazonaws.com"
  STORAGE_SERVICE: "amazon"
  AWS_REGION: "us-west-2"
  AWS_BUCKET: "crewai-prod-storage"
  APPLICATION_HOST: "crewai.company.com"
  AUTH_PROVIDER: "entra_id"

web:
  replicaCount: 3
  ingress:
    enabled: true
    className: "alb"
    host: "crewai.company.com"
    alb:
      certificateArn: "arn:aws:acm:us-west-2:ACCOUNT:certificate/CERT-ID"

buildkit:
  enabled: true

externalSecret:
  enabled: true
  secretStore: "aws-secrets"

Scenario 2: Azure Production Deployment

my-values.yaml
postgres:
  enabled: false

minio:
  enabled: false

envVars:
  DB_HOST: "crewai-prod.postgres.database.azure.com"
  STORAGE_SERVICE: "microsoft"
  AZURE_STORAGE_ACCOUNT_NAME: "crewaistorage"
  APPLICATION_HOST: "crewai.company.com"
  AUTH_PROVIDER: "entra_id"

web:
  replicaCount: 3
  ingress:
    enabled: true
    className: "nginx"
    host: "crewai.company.com"

secretStore:
  enabled: true
  provider: "azure"
  azure:
    vaultUrl: "https://crewai-vault.vault.azure.net"

Scenario 4: Development/Testing Environment

postgres:
  enabled: true
  resources:
    limits:
      cpu: "1"
      memory: "2Gi"

minio:
  enabled: true

web:
  replicaCount: 1
  service:
    type: LoadBalancer
  tls:
    autoGenerate: true

worker:
  replicaCount: 1

envVars:
  RAILS_LOG_LEVEL: "debug"
  AUTH_PROVIDER: "local"
  STORAGE_SERVICE: "amazon"
  AWS_ENDPOINT: "http://crewai-minio:9000"

secrets:
  DB_PASSWORD: "dev-password"