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:
# 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.
Option B: External Secret Store (Recommended for Enterprise)
# 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:
- Register an application in Azure Active Directory
- Configure redirect URIs:
https://your-domain/auth/entra_id/callback
- Generate a client secret in the app registration
- 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:
- Create an application integration in Okta Admin Console
- Choose “OIDC - OpenID Connect” as the sign-in method
- Select “Web Application” as the application type
- Configure Sign-in redirect URIs:
https://your-domain/auth/okta/callback
- 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:
- Create a new application in WorkOS Dashboard
- Configure the redirect URI:
https://your-domain/auth/workos/callback
- Note the Client ID from the application configuration
- 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):
- After deployment, a setup Job runs automatically
- Job waits for PostgreSQL and MinIO availability (when enabled)
- Executes
rails db:migrate for main database
- Executes
rails db:migrate:cable for ActionCable database
- Executes
rails db:seed to populate initial data
- Executes
rake data:migrate to apply data migrations
- Sets up default permissions and syncs feature flags
- Job retries up to 10 times on failure
During Upgrades (helm upgrade):
- Before each upgrade, a pre-upgrade Job runs automatically
- Job waits for PostgreSQL availability (when using internal PostgreSQL)
- Executes
rails db:migrate for main database
- Executes
rails db:migrate:cable for ActionCable database
- Executes
rake data:migrate to apply data migrations
- Job retries up to 3 times on failure
- 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
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"