Skip to main content

Overview

This guide covers Azure-specific integration for CrewAI Platform deployments on Azure Kubernetes Service (AKS). It focuses on how CrewAI uses Azure services and the platform-specific configuration required, rather than general Azure setup.
This guide assumes you have:
  • An AKS cluster running Kubernetes 1.27+ with at least 3 nodes (4 vCPU / 8 GB RAM minimum per node)
  • Azure CLI installed and authenticated (az login)
  • Helm 3.10+ and kubectl configured for your cluster
  • Basic familiarity with Azure services (Azure Database for PostgreSQL, Azure Blob Storage, ACR)

Prerequisites

Before configuring CrewAI Platform, ensure these Azure components are in place: CrewAI Platform supports AMD64 (x86_64) Kubernetes worker nodes. ARM64 (aarch64) worker nodes are not currently supported. For full platform requirements, see the Requirements Guide.

Required Azure Infrastructure

Do not proceed with CrewAI installation until these prerequisites are met. The Helm chart will fail to deploy without them.

Azure Database for PostgreSQL Flexible Server

CrewAI Platform requires PostgreSQL 16 for production deployments. This section covers Azure Database for PostgreSQL Flexible Server requirements.

Instance Sizing

Minimum recommended specifications based on CrewAI workload characteristics:
Memory-optimized SKUs (Standard_E family) provide better performance for CrewAI’s connection-heavy Rails architecture. For production workloads, enable high availability with a standby replica.

Create the PostgreSQL Instance

Network Connectivity

CrewAI pods must reach your PostgreSQL instance. Two options: Option 1: Private Access via VNet Integration (Recommended)
  • Deploy the Flexible Server into the same VNet as your AKS cluster using a delegated subnet
  • No public internet exposure
  • PostgreSQL (5432) is reachable only from within the VNet
Option 2: Public Access with Firewall Rules
  • Enable public access and restrict by AKS outbound IP ranges
  • Requires SSL/TLS enforcement

Database Setup

Azure Database for PostgreSQL only lets you create extensions that are on the server’s azure.extensions allow-list. Allow the extensions the platform uses before you install:
The value replaces the whole allow-list. If the server already allows other extensions, keep them in the list.
CrewAI requires four databases — primary, cable, OAuth, and Wharf for OTLP trace storage:
Create all four databases before running helm install. The Wharf migration will fail at install time if the wharf database does not exist. The Helm chart does not automatically create databases when postgres.enabled: false.

Using a Dedicated Application Role

The examples above connect as the server’s admin user (crewai). If the platform connects with a dedicated role that is not the server admin, that role needs three more things:
  1. CREATEDB. The setup job runs rails db:create on every install, even when the databases already exist, and fails without this attribute.
  2. Ownership of the public schema in each of the four databases. On Azure Database for PostgreSQL, the public schema of a new database belongs to azure_pg_admin, so migrations fail with permission denied for schema public.
  3. The vector extension, created by the admin. vector is not a trusted extension, so only members of azure_pg_admin can create it, even when it is on the allow-list. On Azure this check applies even when the extension already exists, so the platform’s role cannot enable it during setup: the column that uses it is skipped and no error is shown. The admin creates the extension, and the platform’s role then adds the column after the first install.
Before the first install, run as the server admin, replacing <app_role> with the platform’s role:
Then set envVars.DB_USER to that role. After the first install, connect to crewai_plus_production as the platform’s role and add the column that uses vector. The statements are idempotent, so you can also run them on an existing installation:

Helm Configuration

Azure Blob Storage for Object Storage

CrewAI Platform uses Azure Blob Storage for storing crew artifacts, tool outputs, and user uploads when STORAGE_SERVICE is set to "microsoft".

Create Storage Account and Container

The name you choose for the container (e.g., crewai-storage) becomes the value for AZURE_CONTAINER_NAME in your Helm values, and AZURE_STORAGE_ACCOUNT_NAME is the storage account name. If AZURE_CONTAINER_NAME is empty, CrewAI Platform uses a container named crewai-plus-production, which must then exist in the account.
Upgrading an existing Azure installation: earlier platform releases ignored AZURE_CONTAINER_NAME and always stored files in the crewai-plus-production container. If your existing files are there, set AZURE_CONTAINER_NAME: "crewai-plus-production" before upgrading, or copy the blobs to the container you configured.

Storage Authentication Options

CrewAI supports two authentication methods for Azure Blob Storage. Choose based on your security requirements: Best for: Production AKS deployments, highest security. No long-lived credentials stored in Kubernetes secrets. Azure Workload Identity binds an AKS pod’s service account to an Azure Managed Identity (or App Registration) via federated credential trust — no static keys required. Setup Steps:
  1. Enable the AKS OIDC Issuer and Workload Identity:
  1. Create a User-Assigned Managed Identity:
  1. Grant Storage Blob Data Contributor role to the Managed Identity:
  1. Create Federated Credential for AKS:
The federated credential links the AKS service account to the managed identity. The crewai-sa service account name is the chart default when rbac.create: true.
The --subject value must exactly match the Kubernetes namespace and ServiceAccount name. With rbac.create: true (the default), the chart creates crewai-sa in the Helm release namespace. Adjust both crewai parts if you deploy to a different namespace or use a custom ServiceAccount name.
Helm Configuration:
When rbac.create: true (the default), the chart automatically creates a ServiceAccount named crewai-sa. Setting serviceAccount.azureWorkloadIdentity: true adds the azure.workload.identity/use: "true" label to platform pods, enabling the AKS Workload Identity webhook to inject federated credentials. The federated credential must reference this exact ServiceAccount name and namespace.
AZURE_CONTAINER_NAME is the name of the blob container within the storage account, not the storage account name itself. It must match the container you created with az storage container create --name crewai-storage. If it is empty, the platform uses a container named crewai-plus-production.

Option 2: Storage Access Key

Best for: Development environments or deployments outside AKS where managed identity is not available.
Not recommended for production. Use Workload Identity instead to avoid storing long-lived credentials in Kubernetes secrets.
AZURE_CONTAINER_NAME is the name of the blob container within the storage account (e.g., crewai-storage), not the storage account name itself. It must match the container you created in Azure. If it is empty, the platform uses a container named crewai-plus-production.

Azure Container Registry (ACR) for Crew Images

CrewAI Platform requires a writable container registry to build and push crew automation container images. When users create and deploy crews, CrewAI builds container images and pushes them to ACR.

ACR Repository Requirements

Critical Requirements:
  • The repository path set in CREW_IMAGE_REGISTRY_OVERRIDE must be a writable ACR registry prefix
  • The platform automatically appends /crewai-enterprise to the value — ensure the resulting repository exists and allows push/pull
  • ACR webhook retention and tag mutability: CrewAI overwrites image tags for crew versions, so immutable tags must not be enforced on the target repository
  • Chart installation fails if CREW_IMAGE_REGISTRY_OVERRIDE is not set

Create ACR and Repository

Valid CREW_IMAGE_REGISTRY_OVERRIDE values:
  • crewairegistry.azurecr.io — appends /crewai-enterprise automatically
  • crewairegistry.azurecr.io/production — appends /crewai-enterprise automatically
  • crewairegistry.azurecr.io/my-org — appends /crewai-enterprise automatically
Do NOT set global.imageRegistry to your ACR host. This redirects ALL platform component image pulls (Redis, Wharf, BuildKit, busybox, the main application) away from images.crewai.com, causing ImagePullBackOff on every platform pod. Only CREW_IMAGE_REGISTRY_OVERRIDE is needed for crew image builds. Only use global.imageRegistry if you have mirrored every platform image to ACR per the private-registry guide.

ACR Authentication with Workload Identity

CrewAI pods require ACR push and pull permissions for building and deploying crew images. Grant AcrPush to the Managed Identity (uses the same identity created for Blob Storage):
The crews namespace federated credential below is needed only with the BuildKit provider (envVars.PROVIDER: BUILDKIT_KUBERNETES). With the default no-build provider (KUBERNETES_V3), crews are not built in the cluster and do not push images to ACR. If your crew code calls Azure APIs with Workload Identity on the no-build provider, contact CrewAI Support.
For crew pods running in the crewai-crews namespace (build pods that push images), you also need a federated credential for that namespace’s default service account. Create this after the first helm install, which automatically creates the crewai-crews namespace:
The kubectl annotate command must run after the first helm install because the Helm chart creates the crewai-crews namespace. If you need to annotate before installing, create the namespace manually first: kubectl create namespace crewai-crews.
ArgoCD users: This step requires a two-Application pattern because the crewai-crews namespace does not exist until after the first sync completes. See the ArgoCD Deployment Guide.

ACR Authentication with Static Credentials

For environments where managed identity is not available, you can use an ACR service principal with static credentials:
ACR service principal tokens and passwords are long-lived credentials. Rotate them regularly and store them in Azure Key Vault rather than directly in Kubernetes secrets. Use Workload Identity for production deployments.

Helm Configuration for ACR

Combined Workload Identity Setup (Storage + ACR)

When using Workload Identity for both Blob Storage and ACR (recommended), a single managed identity covers both:

Verifying ACR Access

Test ACR authentication from CrewAI pods:

Gateway API

CrewAI Platform exposes the web application through the Kubernetes Gateway API. On AKS you can use either of two implementations, and you choose one with gateway.gatewayClassName: Both implementations terminate TLS at the Gateway and forward plain HTTP to the web pods, so set web.enableSslFromPuma: false. Both health-check the web pods through their readiness probe, so no extra health check resource is needed.

Enable the Managed Gateway API

Both options use the Gateway API CRDs that AKS installs and manages:

Option 1: App Routing

Enable the App Routing implementation of the Gateway API:
Helm configuration:
After installation, point an A record for your hostname at the Gateway address:

Preserve the Client IP

By default, the Load Balancer Service that App Routing creates for the Gateway uses externalTrafficPolicy: Cluster, so the platform sees a node IP instead of the client IP. The platform uses the client IP for rate limiting and audit records, so preserve it. Create a ConfigMap in the release namespace that sets externalTrafficPolicy: Local on the Gateway Service. Because App Routing points the Azure Load Balancer health probe at a fixed port by default, the ConfigMap also sets a health check node port and points the probe at it. Choose a port in the node port range (30000-32767) that no other Service uses:
Reference it from the Gateway:
Do not set externalTrafficPolicy: Local without also moving the health probe to the health check node port. Otherwise the Azure Load Balancer keeps sending traffic to nodes that have no Gateway pod, and a share of requests fails.

Internal Load Balancer

To expose the Gateway only inside your virtual network, add the Azure annotation to the Gateway Service:

Option 2: Application Gateway for Containers

  1. Install the ALB Controller with Helm by following the Microsoft quickstart. Because AKS manages the Gateway API CRDs, add --set albController.installGatewayApiCRDs=false to the helm install command. Without it, the controller pods fail to start because AKS rejects changes to the managed CRDs.
  2. Create the Application Gateway for Containers resource. With the deployment managed by the ALB Controller, define an ApplicationLoadBalancer that uses a subnet delegated to Microsoft.ServiceNetworking/trafficControllers (see the Microsoft quickstart):
  3. Configure the chart to use it:
  4. After installation, point a CNAME record for your hostname at the Gateway address:

TLS Certificates

The HTTPS listener reads its certificate from the Kubernetes TLS Secret named in certificateRefs. You can create the Secret yourself:
Or let cert-manager issue and renew it through the Gateway:
  1. Enable Gateway API support in cert-manager:
  2. Create a ClusterIssuer that solves HTTP-01 challenges through the Gateway’s HTTP listener:
  3. Annotate the Gateway. cert-manager creates a Certificate for each HTTPS listener that has a hostname and a certificateRefs entry:
The HTTP listener must stay reachable from the internet for HTTP-01 challenges. With gateway.httpsRedirect.enabled: true, every other request on that listener is redirected to HTTPS.

Microsoft Entra ID Authentication

CrewAI Platform uses Microsoft Entra ID (formerly Azure Active Directory) for enterprise SSO. Full setup instructions are in the Microsoft Entra ID Guide, but the key Helm values are:

Helm Configuration

The callback URL you register in Entra ID must match your application host and use the path /auth/entra_id/callback. For example: https://crewai.your-company.com/auth/entra_id/callback.

Azure Key Vault Integration

Azure Key Vault provides centralized secret management with audit logging for CrewAI Platform. The chart integrates with Key Vault via External Secrets Operator (ESO).

Which Secrets to Store

Store in Azure Key Vault (sensitive, need rotation):
  • DB_PASSWORD — Database credentials
  • SECRET_KEY_BASE — Rails secret key
  • ENTRA_ID_CLIENT_SECRET — Entra ID OAuth secret
  • AZURE_STORAGE_ACCESS_KEY — If using access key auth for storage
  • GITHUB_TOKEN — For private repository access
Keep in values.yaml (configuration, not secrets):
  • DB_HOST, DB_PORT, DB_USER, POSTGRES_DB, POSTGRES_CABLE_DB
  • AZURE_STORAGE_ACCOUNT_NAME, AZURE_CONTAINER_NAME
  • APPLICATION_HOST
  • AUTH_PROVIDER, ENTRA_ID_CLIENT_ID, ENTRA_ID_TENANT_ID

Create Key Vault

Grant Key Vault Secrets Officer to Managed Identity

Install External Secrets Operator

Helm Configuration for Key Vault

The chart’s secretStore block creates a SecretStore resource pointing to Azure Key Vault. Use Workload Identity authentication (recommended) or Service Principal. Using Workload Identity:
Using Service Principal (alternative):

Complete Azure Deployment Example

If using WorkOS authentication, place WORKOS_API_KEY under envVars: — NOT under secrets:. See the WorkOS SSO guide for the full explanation and the correct YAML placement. This is a known chart limitation.
Here is a complete production configuration for Azure using Workload Identity for all services:
Deploy:

Troubleshooting Azure-Specific Issues

Pods Fail to Pull Images from images.crewai.com

Symptoms: Platform pods show ImagePullBackOff or ErrImagePull on images from images.crewai.com First check — verify global.imageRegistry is not set to ACR: Setting global.imageRegistry to your ACR host redirects all platform image pulls away from images.crewai.com. Check your values file for this pattern and remove it:
Common causes:
  1. global.imageRegistry was set to the ACR hostname — this redirects all platform image pulls away from images.crewai.com
Resolution: Remove global.imageRegistry from your values. Only CREW_IMAGE_REGISTRY_OVERRIDE should reference ACR.

Workload Identity Not Working — Access Denied to Blob Storage

Symptoms: Logs show AuthorizationPermissionMismatch or 403 errors for Blob Storage operations Verify the OIDC issuer and federated credential:
Verify the ServiceAccount annotation:
Check pod labels (Workload Identity requires the azure.workload.identity/use: "true" label on pods, enabled via serviceAccount.azureWorkloadIdentity: true):
Test from pod:

PostgreSQL Connection Timeout

Symptoms: Pods show could not connect to server: Connection timed out Check VNet connectivity:
Check firewall rules:
Verify private DNS zone (if using VNet integration):

ACR Push Fails — Unauthorized

Symptoms: BuildKit logs show unauthorized: authentication required when pushing crew images Verify the AcrPush role assignment:
Verify the crews namespace federated credential:
Check the default ServiceAccount annotation in the crews namespace:

Key Vault ExternalSecret Sync Errors

Symptoms: ExternalSecret shows SecretSyncedError
Verify Key Vault access policy:

ServiceAccount Mismatch with Workload Identity

Symptoms: Pods show AuthorizationFailed despite correct Azure role assignments Common causes:
  1. Wrong ServiceAccount name in federated credential — The --subject in the federated credential must exactly match the namespace and ServiceAccount name used by pods
  2. Missing azure.workload.identity/use: "true" label — Pods without this label do not receive federated tokens. Enable via serviceAccount.azureWorkloadIdentity: true
Diagnosis: