Dify Enterprise Edition Deployment Guide (AWS)
This document describes how to deploy Dify Enterprise Edition in an AWS cloud environment. You can choose any of the following methods to complete the deployment:- Via Terraform (Recommended)
- Via CDK
- Manually create infrastructure and deploy (Not recommended)
Option 1: Build via Terraform
Please contact the Dify technical support team to obtain Terraform-related scripts and documentation.
Prerequisites
kubectl,helm, andaws cliare installed locally.- An AWS account with permissions to create the following resources.
- AWS EKS (Elastic Kubernetes Service): For deploying Dify core services; nodes need internet access or NAT Gateway configuration
- AWS S3 (Simple Storage Service): For persistent storage
- AWS ECR (Elastic Container Registry): For Dify plugin installation; can also host Dify images and Helm Charts
- AWS RDS Aurora Postgres: Relational database for storing application data and audit records
- AWS OpenSearch: Vector database for RAG (Retrieval Augmented Generation) related features
- Amazon ElastiCache: Managed Redis caching service for accelerating data access
Option 2: Build via CDK
Please refer to AWS CDK Deployment.Option 3: Manually Create Infrastructure and Deploy
1. Create Infrastructure
Please refer to the recommended configurations in the table below and create infrastructure according to your actual needs. (Replace content in double brackets with actual values)Version note (important): The versions in the table below are provided as “available ranges/version families” for reference. Before deployment, please make sure to verify in the AWS Console of your target AWS Region (or via AWS CLI) which versions are currently supported (EKS Kubernetes, Aurora PostgreSQL, OpenSearch, ElastiCache Redis, etc.) to avoid resource creation failures caused by regional differences or version deprecations.
Testing Environment Infrastructure Configuration Reference
Note: If enabling the unstructured service on a single node, increase disk capacity to 40 GB.
| Component Type | Configuration Item | Specification | Description |
|---|---|---|---|
| EKS Cluster | Cluster Name | dify-{your_custom_deployment_id}-eks-cluster | Custom naming |
| Kubernetes Version | 1.2x–1.3x (subject to what EKS supports in the target Region) | Pre-launch check: EKS Kubernetes version support list for the target Region | |
| Node Instance Type | m7a.xlarge (amd64) / m7g.xlarge (arm64) | 4 vCPU, 16GB RAM | |
| Node Count | 1-2 (desired: 1) | Minimum cost configuration | |
| Node Disk Size | 40 GB | gp3, encrypted | |
| AMI Type | AL2023_x86_64 / ARM_64_STANDARD | Amazon Linux 2023 | |
| S3 Bucket | Bucket Name | dify-{your_custom_deployment_id}-storage | Custom naming |
| Versioning | Enabled | File version management | |
| Encryption | AES256 | Server-side encryption | |
| Public Access | Fully blocked | Security configuration | |
| Storage Capacity Planning | 100GB | Testing environment capacity | |
| RDS (Aurora Serverless v2) | Cluster Identifier | dify-{your_custom_deployment_id}-aurora-postgres | Custom naming |
| Engine Version | Aurora PostgreSQL (PostgreSQL 14+ compatible, subject to target Region support) | Pre-launch check: available Aurora PostgreSQL engine versions in the target Region | |
| Instance Count | 1 | Single instance, cost optimized | |
| Instance Type | db.serverless | Serverless v2 dedicated | |
| Min/Max Capacity | 1 - 8 ACU | Auto scaling | |
| Storage Encryption | Enabled | At-rest encryption | |
| Backup Retention | 7 days | Automatic backup | |
| Performance Insights | Disabled | Cost optimization | |
| Create Databases | dify, enterprise, audit, dify_plugin_daemon | 4 databases | |
| OpenSearch | Domain Name | dify-{your_custom_deployment_id}-opensearch | Custom naming |
| Engine Version | OpenSearch 2.x (subject to target Region support) | Pre-launch check: supported engine versions for Amazon OpenSearch Service | |
| Instance Type | t3.medium.search | 2 vCPU, 4 GB RAM | |
| Instance Count | 1 | Single node | |
| Storage Type/Size | EBS gp3 / 100 GB | Testing environment (single node) | |
| Security Features | At-rest encryption, node-to-node encryption, HTTPS enforced | Comprehensive security | |
| ElastiCache (Redis) | Replication Group ID | dify-{your_custom_deployment_id}-redis | Custom naming |
| Engine Version | Redis 7.x (subject to what ElastiCache supports in the target Region) | Pre-launch check: supported engine versions for ElastiCache for Redis | |
| Node Type | cache.t4g.small | 2 vCPU, 1.37 GB RAM | |
| Cache Node Count | 1 | Single node mode | |
| Multi-AZ | Disabled | Single AZ deployment | |
| Snapshot Retention | 0 days | No backup | |
| IAM Roles | EKS Cluster Role | dify-{your_custom_deployment_id}-cluster-role | AmazonEKSClusterPolicy |
| EKS Node Group Role | dify-{your_custom_deployment_id}-node-group-role | Worker + CNI + ECR policies | |
| S3 Access Role | dify-{your_custom_deployment_id}-s3-role | S3 full access | |
| S3+ECR Access Role | dify-{your_custom_deployment_id}-s3-ecr-role | S3 + ECR full access | |
| ECR Pull Role | dify-{your_custom_deployment_id}-ecr-pull-role | ECR read-only access | |
| Other Resources | ECR Repository | 2 (main app + plugins) | Image storage |
| Secrets Manager | 1 | RDS credentials |
Production Environment Infrastructure Configuration Reference
| Component Type | Configuration Item | Specification | Description |
|---|---|---|---|
| EKS Cluster | Cluster Name | dify-{your_custom_deployment_id}-eks-cluster | Custom naming |
| Kubernetes Version | 1.2x–1.3x (subject to what EKS supports in the target Region) | Pre-launch check: EKS Kubernetes version support list for the target Region | |
| Node Instance Type | m7a.xlarge (amd64) / m7g.xlarge (arm64) | 4 vCPU, 16GB RAM | |
| Node Count | 6-10 (desired: 6) | Production environment configuration | |
| Node Disk Size | 20 GB | gp3, encrypted | |
| AMI Type | AL2023_x86_64 / ARM_64_STANDARD | Amazon Linux 2023 | |
| S3 Bucket | Bucket Name | dify-{your_custom_deployment_id}-storage | Custom naming |
| Versioning | Enabled | File version management | |
| Encryption | AES256 | Server-side encryption | |
| Public Access | Fully blocked | Security configuration | |
| Storage Capacity Planning | 512GB | Production environment capacity | |
| RDS (Aurora Serverless v2) | Cluster Identifier | dify-{your_custom_deployment_id}-aurora-postgres | Custom naming |
| Engine Version | Aurora PostgreSQL (PostgreSQL 14+ compatible, subject to target Region support) | Pre-launch check: available Aurora PostgreSQL engine versions in the target Region | |
| Instance Count | 1 | Single instance, cost optimized | |
| Instance Type | db.serverless | Serverless v2 dedicated | |
| Min/Max Capacity | 4 - 8 ACU | Auto scaling | |
| Storage Encryption | Enabled | At-rest encryption | |
| Backup Retention | 30 days | Automatic backup | |
| Performance Insights | Enabled | Recommended to enable in production | |
| Create Databases | dify, enterprise, audit, dify_plugin_daemon | 4 databases | |
| OpenSearch | Domain Name | dify-{your_custom_deployment_id}-opensearch | Custom naming |
| Engine Version | OpenSearch 2.x (subject to target Region support) | Pre-launch check: supported engine versions for Amazon OpenSearch Service | |
| Instance Type | r5.large.search | 2 vCPU, 16 GB RAM (per node) | |
| Instance Count | 3 | 3-node cluster, total 6 vCPU, 48 GB RAM | |
| Storage Type/Size | EBS gp3 / 30 GB | 30 GB per node | |
| Security Features | At-rest encryption, node-to-node encryption, HTTPS enforced | Comprehensive security | |
| ElastiCache (Redis) | Replication Group ID | dify-{your_custom_deployment_id}-redis | Custom naming |
| Engine Version | Redis 7.x (subject to what ElastiCache supports in the target Region) | Pre-launch check: supported engine versions for ElastiCache for Redis | |
| Node Type | cache.t4g.medium | ~2 vCPU, ~3 GB RAM | |
| Cache Node Count | 2 | Primary + read replica | |
| Auto Failover | Enabled | High availability | |
| Multi-AZ | Enabled | Cross-AZ deployment | |
| Snapshot Retention | 7 days | Automatic backup | |
| IAM Roles | EKS Cluster Role | dify-{your_custom_deployment_id}-cluster-role | AmazonEKSClusterPolicy |
| EKS Node Group Role | dify-{your_custom_deployment_id}-node-group-role | Worker + CNI + ECR policies | |
| S3 Access Role | dify-{your_custom_deployment_id}-s3-role | S3 full access | |
| S3+ECR Access Role | dify-{your_custom_deployment_id}-s3-ecr-role | S3 + ECR full access | |
| ECR Pull Role | dify-{your_custom_deployment_id}-ecr-pull-role | ECR read-only access | |
| Other Resources | ECR Repository | 2 (main app + plugins) | Image storage |
| Secrets Manager | 1 | RDS credentials |
2. Configure values.yaml
After creating the database, S3, and other infrastructure, please refer to the following example to configurevalues.yaml (replace content in double brackets with actual values). Before this, you need to create four databases in the database: dify, enterprise, audit, dify_plugin_daemon, and replace the corresponding configuration items such as rds_main_database_name in values.yaml.
3. Configure S3 and ECR Permissions
To ensure Dify services start properly and the plugin system functions correctly, theapi, worker, workerBeat, plugin_daemon, and plugin_connector services require S3 access permissions, and the plugin_connector service also requires ECR access permissions. The specific reasons why the plugin_connector service needs these permissions will be explained in detail later.
You can configure permissions in one of the following two ways:
- IRSA Mode: IAM Roles for Service Accounts, enabling secure and fine-grained permission control (Recommended)
- Access Key (AK/SK) Mode: Provide credentials via environment variables
IRSA Mode Configuration
Dify recommends using IRSA to configure ServiceAccount permissions. You can contact the Dify technical support team forone-click IRSA deployment scripts.
IRSA establishes a trust relationship between the EKS cluster and IAM through an OIDC Provider, allowing Pods to securely obtain AWS permissions via ServiceAccounts without configuring Access Keys in the Pod. The overall architecture is as follows:
| Service Account | Component | Permission Description | Scope |
|---|---|---|---|
dify-enterprise | Enterprise service | Has get, list, watch permissions for namespaces, used to retrieve and watch namespace information. | Role (namespace level) |
dify-plugin-sa | Plugin Controller | Has full management permissions for difyplugins (CRD) and their finalizers/status, leases, events, services, configmaps, deployments, jobs, ingresses, and other resources. | Role (plugin namespace) |
dify-plugin-connector-sa | Plugin Connector & Daemon | Inherits permissions from dify-plugin-connector-role (same as dify-plugin-sa). | Role (plugin namespace) |
| Custom Service Account | Various service components | Empty by default (uses default service account), can be configured via values.yaml. | As configured |
customServiceAccount | Plugin custom service account | For custom permissions during plugin runtime, empty by default, can be specified via configuration. | As configured |
runnerServiceAccount | Plugin Runner service account | Dedicated service account for plugin runner, empty by default, can be specified via configuration. | As configured |
💡 Special Note About CRD Installation Dify Enterprise Edition only requires namespace-level permissions during installation. However, since CRD itself is a cluster-level resource, appropriate cluster permissions are required during installation. If you don’t have cluster-level permissions, you can install the CRD separately first, then install the remaining components. The CRD itself is just an API structure declaration registered in Kubernetes. When its corresponding Controller is namespace-level, it cannot access or modify resources across namespaces.
Step 1: Verify IAM OIDC Provider
Before configuring IRSA, ensure the cluster has IAM OIDC Provider enabled. If the cluster was created manually, it’s recommended to enable or verify using theeksctl command-line tool. The IAM OIDC Provider establishes a trust relationship that allows the EKS cluster to prove Pod identity to IAM, enabling Pods to securely obtain AWS permissions.
Step 2: Create AWS IAM Policies
You need to create the following three IAM policies: Policy 1: S3 Access Policy (name is customizable, e.g.DifyS3Policy)
DifyECRPolicy)
Used for plugin image push and management, including ECR authentication, repository management, image push, and audit logging permissions:
Policy 3: ECR Pull-Only Policy (name is customizable, e.g.{your_ecr_repo_prefix}is the name prefix of your ECR repositories. For example, if you configureimageRepoPrefixin Step 5 as123456789.dkr.ecr.us-east-1.amazonaws.com/dify-ee, then the ECR repository prefix here isdify-ee, and the Resource should bearn:aws:ecr:us-east-1:123456789:repository/dify-ee*.
DifyECRPullOnlyPolicy)
Used only for pulling plugin runtime images:
Step 3: Create AWS IAM Roles
Create the following three roles and attach the policies from Step 2 to the corresponding roles (role names can be customized):| Role Name (Example) | Attached Policies | Purpose |
|---|---|---|
DifyS3Role | S3 Access Policy | S3 storage access |
DifyS3ECRRole | S3 Access Policy + ECR Full Access Policy | S3 + ECR image push/management |
DifyECRPullRole | ECR Pull-Only Policy | ECR image pull |
Replace{oidc_id}with the OIDC Provider ID of your EKS cluster. You can obtain it with the following command:
Step 4: Bind Roles to EKS ServiceAccounts
ServiceAccount (SA) is a mechanism that allows Pods in EKS to obtain specific AWS permissions to access cloud resources (such as S3).Create the following four ServiceAccounts and add the corresponding role ARN to the
eks.amazonaws.com/role-arn annotation:
| ServiceAccount | Namespace | Bound Role | Effective Permissions |
|---|---|---|---|
dify-api-sa | dify | S3 Access Role | S3 access |
dify-plugin-crd-sa | dify | S3+ECR Access Role | S3 + ECR push/pull |
dify-plugin-runner-sa | dify | ECR Pull Role | ECR pull only |
dify-plugin-connector-sa | dify | S3 Access Role | S3 access (auto-assigned by Helm) |
$DIFY_EE_* with the role ARNs obtained in Step 3):
Step 5: Configure ServiceAccount in values.yaml
Modify Helm’svalues.yaml and add the following configuration (only ServiceAccount and ECR-related configurations are shown below, other configurations are omitted). imageRepoPrefix can be customized:
‼️dify-plugin-connector-sawill be automatically assigned to theplugin_connectorservice through Helm Chart templates;dify-plugin-crd-saanddify-plugin-runner-sawill be used for Pods that build and run plugins.
Access Key Mode Configuration
Step 1: Prepare Credentials
Create an IAM user with only S3 and ECR permissions, and obtain its Access Key and Secret Key.Step 2: Create Kubernetes Secret
plugin_connector service via imageRepoSecret in values.yaml in the next step.
Step 3: Configure values.yaml
4. Install AWS ALB (Application Load Balancer)
To make Dify Enterprise Edition accessible via domain name, you need to install AWS ALB (Application Load Balancer). You can also choose to use Nginx Ingress Controller or other Ingress Controllers. AWS ALB is recommended because it integrates seamlessly with Dify Enterprise Edition and provides better performance and scalability. Please visit https://docs.aws.amazon.com/eks/latest/userguide/lbc-manifest.html for the AWS ALB installation guide.If you cannot install AWS ALB, you can use Nginx Ingress Controller as an alternative:After AWS ALB installation is complete, you can confirm whether the service is running properly with the following command:
values.yaml:
global configuration. You can verify the domain and create a certificate through AWS Certificate Manager.
5. Execute Installation
Please visit https://langgenius.github.io/dify-helm/#/ for detailed installation instructions.
‼️ It is not recommended to install Dify in the default namespace.
6. Verify Service Status
- Update kubectl access credentials:
- Verify EKS nodes are running properly:
- Verify Dify service status:
- Confirm ALB is working properly:
‼️ Please configure the DNSName from the above command output as a CNAME record, resolving to the various domains required by Dify.