はじめに
こんにちは、久保です。
AWSではBedrockをはじめとした様々な生成AIのサービスが提供されています。
生成AIアプリケーションを構築、利用したい場合に、フロントエンドとして何を利用するかについても様々な選択肢がありますが、
本記事ではDifyをお試しで利用したい場合の構築方法についてご紹介します。
AWSの構築ワークショップとして以下URLで提供されているCloudFormationテンプレートをベースに、HTTPSで利用できるようにした構成を紹介します。
Dify での生成 AI アプリケーション構築ワークショップ
本記事のCloudFormationテンプレートを利用することで、簡単にDifyをAWSで試してみたいが通信はHTTPSで暗号化したい というケースに対応可能となります。
- はじめに
- Dify とは
- AWSワークショップのご紹介
- 本記事で紹介する構成について
- CloudFormationテンプレートの紹介
- 利用例
- 参考(Infrastructure Composerで確認)
- 終了後のお掃除
- おわりに
2026/1/16 "Bedrockを利用するためのDifyの初期設定"を追記しました。
Dify とは
Dify is an open-source platform for developing LLM applications.
とあるとおり、LangGenius社が提供している、生成AIアプリケーションを作成するためのオープンソースプラットフォームであり、どなたでも利用することが可能なソフトウェアです。
GUIでアプリケーションの処理を定義することが可能で、非エンジニアの方であっても簡単に生成AIアプリケーションを構築することができます。
生成AIによる業務効率化などの課題解決を、より現場の業務に精通した現場の方々が主体となって実施可能とすることができます。
AWSワークショップのご紹介
先述のとおり、AWSではDifyを利用した生成AIアプリケーションを構築するためのワークショップが提供されています。
こちらを実施することでAWSでDifyを利用した生成AIアプリケーションの構築を簡単に体験することができます。
Dify での生成 AI アプリケーション構築ワークショップ
ただし注意事項に明記されておりますとおり、ワークショップで構築する環境では通信の暗号化や公開アプリの認証、冗長化は実施されないため、本番利用の際には必要なセキュリティを別途施す必要があります。
本記事で紹介する構成について
本記事では最低限、通信についてはCloudFrontを利用してHTTPSで暗号化通信が可能なようにしたCloudFormationテンプレートを紹介します。
注意事項として、PC→CloudFront間の通信はHTTPSで暗号化されますが、CloudFront→EC2間の通信はHTTP通信となります。
あくまでもインターネットを経由する通信を暗号化することを目的としていることをご理解ください。

ベースのテンプレートとの違いは以下のとおりです。
- EC2の前にCloudFrontが配置され、HTTPSでのアクセスが可能となります(CloudFrontのデフォルトドメイン名を利用します)
- アクセスを許可するIPアドレスアドレスを指定した場合は、AWS WAFがCloudFrontにアタッチされ、指定したIPアドレスからのアクセスのみ許可されます
- CloudFront用のAWS WAFはus-east-1で作成する必要があるため、IP制限を行う場合はCloudFormationスタックをus-east-1で作成する必要があります(IP制限しない場合は任意のリージョンで作成可能です)
- EC2のセキュリティグループは、CloudFrontのIPアドレスレンジからのHTTPアクセスのみを許可します
DifyVersionというパラメータで利用するDifyのバージョンを指定可能です(デフォルトは1.11.2)
なお、Amazon Bedrockが米国(オレゴン)となっているのはワークショップ内容をそのまま実施した場合の例です。実際には任意のリージョンでBedrockを利用可能です。
CloudFormationテンプレートの紹介
dify-self-deployment-with-ssl.ymlとして保存してご利用ください。
▼テンプレートを表示する
AWSTemplateFormatVersion: '2010-09-09' Description: Dify CloudFormation Template with HTTPS support Parameters: VpcCIDR: Type: String Default: 192.168.0.0/16 Description: CIDR block for the VPC Subnet1CIDR: Type: String Default: 192.168.0.0/20 Description: CIDR block for Subnet 1 Subnet2CIDR: Type: String Default: 192.168.16.0/20 Description: CIDR block for Subnet 2 AllowedCIDR: Type: String Default: 0.0.0.0/0 Description: CIDR block to allow HTTPS traffic from CloudFront. Set to 0.0.0.0/0 to allow all IPs, or specify a specific CIDR (e.g., 203.0.113.0/24) to restrict access via WAF DifyVersion: Type: String Default: 1.11.2 Description: Dify version to deploy AmazonLinuxAMI: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64 Conditions: EnableIPRestriction: !Not [!Equals [!Ref AllowedCIDR, '0.0.0.0/0']] Mappings: # CloudFront origin-facing managed prefix list IDs by region # aws ec2 describe-managed-prefix-lists --region <REGION> | jq -r '.PrefixLists[] | select (.PrefixListName == "com.amazonaws.global.cloudfront.origin-facing") | .PrefixListId' AWSRegions2PrefixListID: ap-northeast-1: PrefixList: pl-58a04531 ap-northeast-2: PrefixList: pl-22a6434b ap-south-1: PrefixList: pl-9aa247f3 ap-southeast-1: PrefixList: pl-31a34658 ap-southeast-2: PrefixList: pl-b8a742d1 ca-central-1: PrefixList: pl-38a64351 eu-central-1: PrefixList: pl-a3a144ca eu-north-1: PrefixList: pl-fab65393 eu-west-1: PrefixList: pl-4fa04526 eu-west-2: PrefixList: pl-93a247fa eu-west-3: PrefixList: pl-75b1541c sa-east-1: PrefixList: pl-5da64334 us-east-1: PrefixList: pl-3b927c52 us-east-2: PrefixList: pl-b6a144df us-west-1: PrefixList: pl-4ea04527 us-west-2: PrefixList: pl-82a045eb Resources: DifyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCIDR EnableDnsHostnames: true EnableDnsSupport: true InstanceTenancy: default Tags: - Key: Name Value: dify-vpc Subnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref DifyVPC AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Ref Subnet1CIDR Tags: - Key: Name Value: dify-subnet-1 Subnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref DifyVPC AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Ref Subnet2CIDR Tags: - Key: Name Value: dify-subnet-2 InternetGateway: Type: AWS::EC2::InternetGateway VPCGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref DifyVPC InternetGatewayId: !Ref InternetGateway RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref DifyVPC Route: Type: AWS::EC2::Route DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway Subnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref Subnet1 RouteTableId: !Ref RouteTable Subnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref Subnet2 RouteTableId: !Ref RouteTable DifySecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow HTTP traffic from CloudFront only SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourcePrefixListId: !FindInMap [AWSRegions2PrefixListID, !Ref 'AWS::Region', PrefixList] Description: Allow HTTP traffic from CloudFront origin-facing SecurityGroupEgress: - IpProtocol: -1 CidrIp: 0.0.0.0/0 Description: Allow all outbound traffic VpcId: !Ref DifyVPC Tags: - Key: Name Value: dify-sg DifyWsInstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/AmazonBedrockFullAccess' - 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore' InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref DifyWsInstanceRole DifyWsInstance: Type: AWS::EC2::Instance Properties: ImageId: !Ref AmazonLinuxAMI InstanceType: t3.medium NetworkInterfaces: - AssociatePublicIpAddress: 'true' DeviceIndex: '0' GroupSet: - !Ref DifySecurityGroup SubnetId: !Ref Subnet1 BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeSize: 20 VolumeType: gp2 Encrypted: 'true' Tags: - Key: Name Value: dify-ws IamInstanceProfile: !Ref InstanceProfile UserData: Fn::Base64: !Sub | #!/bin/bash max_attempts=5 attempt_num=1 success=false while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do sudo dnf install -y git docker if [ $? -eq 0 ]; then echo "dnf install succeeded" success=true else echo "dnf install $attempt_num failed. trying again..." sleep 3 ((attempt_num++)) fi done sudo systemctl start docker sudo gpasswd -a ec2-user docker sudo gpasswd -a ssm-user docker sudo chgrp docker /var/run/docker.sock sudo service docker restart sudo systemctl enable docker sudo curl -L "https://github.com/docker/compose/releases/download/v2.28.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose cd /opt sudo git clone https://github.com/langgenius/dify.git cd /opt/dify sudo git checkout ${DifyVersion} sudo git pull origin ${DifyVersion} cd /opt/dify/docker sudo cp .env.example .env docker-compose up -d WAFIPSet: Type: AWS::WAFv2::IPSet Condition: EnableIPRestriction Properties: Name: DifyAllowedIPs Scope: CLOUDFRONT IPAddressVersion: IPV4 Addresses: - !Ref AllowedCIDR WAFWebACL: Type: AWS::WAFv2::WebACL Condition: EnableIPRestriction Properties: Name: DifyCloudFrontWAF Scope: CLOUDFRONT DefaultAction: Block: {} Rules: - Name: AllowSpecificIPs Priority: 0 Statement: IPSetReferenceStatement: Arn: !GetAtt WAFIPSet.Arn Action: Allow: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: AllowSpecificIPsRule VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: DifyCloudFrontWAF CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Enabled: true Comment: Dify CloudFront Distribution with HTTPS WebACLId: !If [EnableIPRestriction, !GetAtt WAFWebACL.Arn, !Ref 'AWS::NoValue'] DefaultCacheBehavior: TargetOriginId: DifyEC2Origin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD - OPTIONS - PUT - POST - PATCH - DELETE CachedMethods: - GET - HEAD - OPTIONS ForwardedValues: QueryString: true Headers: - '*' Cookies: Forward: all MinTTL: 0 DefaultTTL: 0 MaxTTL: 0 Origins: - Id: DifyEC2Origin DomainName: !GetAtt DifyWsInstance.PublicDnsName CustomOriginConfig: HTTPPort: 80 OriginProtocolPolicy: http-only PriceClass: PriceClass_All Outputs: CloudFrontURL: Description: CloudFront Distribution URL (HTTPS enabled) Value: !Sub 'https://${CloudFrontDistribution.DomainName}' Export: Name: DifyCloudFrontURL InstancePublicIP: Description: Public IP of the EC2 instance (Direct access is restricted to CloudFront) Value: !GetAtt DifyWsInstance.PublicIp Export: Name: DifyInstancePublicIP InstanceId: Description: InstanceId of the EC2 instance Value: !Ref DifyWsInstance Export: Name: DifyInstanceId
利用例
CloudFormationスタックの作成
AWSマネジメントコンソールにログインし、CloudFormationのサービスページに移動します。
構築したいリージョンを選択し、「スタックの作成」をクリックします。
以下ではIP制限も行うために米国(バージニア北部)リージョンを例にしています。

「テンプレートファイルのアップロード」を選択し、先ほど保存したdify-self-deployment-with-ssl.ymlファイルを選択します。
「次へ」をクリックします。

スタック名に任意の名前、例) "dify-on-aws"を入力し、必要に応じてパラメータを変更します。
| パラメータ | 説明 | デフォルト値 |
|---|---|---|
| AllowedCIDR | CloudFront経由でのHTTPSアクセスを許可するCIDRブロック。例えば1.2.3.4/32といった形式で指定します。すべてのIPアドレスからのアクセスを許可する場合は0.0.0.0/0を指定します。 |
0.0.0.0/0 |
| AmazonLinuxAMI | EC2インスタンスに使用するAmazon Linux 2023のAMI ID。デフォルトでは最新のAMI IDがSSMパラメータストアから取得されます。 | /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64 |
| DifyVersion | デプロイするDifyのバージョン。 | 1.11.2 |
| Subnet1CIDR | サブネット1のCIDRブロック。 | 192.168.0.0/20 |
| Subnet2CIDR | サブネット2のCIDRブロック。 | 192.168.16.0/20 |
| VpcCIDR | VPCのCIDRブロック。 | 192.168.0.0/16 |
通常、お試しで利用いただく場合は AllowedCIDR の設定のみ変更し、他のパラメータはデフォルト値のままで問題ありません。
本記事では AllowedCIDR に IPを指定した場合を例とします。
パラメータを入力しましたら「次へ」をクリックします。

"スタックオプションの設定"画面となります。最下部までスクロールし、AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。にチェックを入れ、「次へ」をクリックします。

"確認して作成"の画面となります。内容を確認し、「送信」をクリックします。

スタックの作成が開始されます。
WAFの作成まで含めて概ね5分程度で完了します。
ステータスが"CREATE_COMPLETE"となれば完了です。
「出力」タブをクリックします。

CloudFrontURLの値をクリックします。

これで、HTTPSでDifyの初期画面にアクセスできることが確認できます。
管理者として登録するメールアドレス、任意のユーザ名、パスワードを設定します。

Bedrockを利用するためのDifyの初期設定
DifyでBedrockを利用するために、モデルの設定を行う必要があります。
画面右上のアイコンをクリックし、設定画面にアクセスします。

「モデルプロバイダー」をクリックし「Amazon Bedrock」の「インストール」をクリックします。

「インストール」をクリックします。

インストール後、「セットアップ」をクリックします。

リージョンをBedrockを利用したいリージョンに指定し、「保存」をクリックします。

「システムモデル設定」をクリックします。

システム推論モデル、埋め込みモデル、Rerankモデルをそれぞれ任意のモデルを指定し、保存します。
図は一例です。
これらはデフォルトでDifyで利用されたり、会話のタイトルの生成などのシステムでのLLM利用時に使用されます。
Bedrockの場合音声-to-テキストモデル、テキスト-to-音声モデル は指定できないため空欄とします。
Rerankモデルはリージョンによって利用できない場合があります。
例えば us-east-1 の場合は cohere.rerank-v3-5:0 が利用可能です。

最後に、表示するモデルの設定をご紹介します。
「モデルの表示」をクリックします。

こちらでモデルのオンオフが可能です。
普段利用しないモデルはオフにしておくことで、アプリを作成する際に非表示にすることができます。

その他Difyの設定についてはAWSワークショップの内容や、弊社の過去記事もご参照ください。
参考(Infrastructure Composerで確認)
本例で構築されるリソースをInfrastructure Composerで確認すると以下のようになります。

終了後のお掃除
Difyのお試しが終了しましたら、CloudFormationスタックを削除してリソースをクリーンアップしてください。

おわりに
本記事ではDifyをAWS上に構築する際に、HTTPSでアクセス可能とする構成をCloudFormationテンプレートで紹介しました。
あくまでシンプルにHTTPSでアクセス可能とすることを目的としているため、CloudFrontのオリジンは直接EC2を指定する形となっています。
EC2はプライベートサブネットに配置してVPCオリジンを利用する、もしくはALBを間に配置するなど、本番利用にあたってはよりセキュアな構成をご検討いただく必要がございます。
Dify on AWS を可能な限り簡単に、かつ最低限のセキュリティを確保して試したい場合に、本記事の内容がお役に立てば幸いです。
久保 賢二(執筆記事の一覧)
猫とAWSが好きです。