Amazon Linux 2023上にHTTPSで保護されたDifyを新規構築する
Amazon Linux 2023上にDockerでDifyを起動する手順をメモしておきます。Difyを構成するコンテナ群にはcert-botコンテナが含まれており、サーバ証明書を新規取得・更新する能力を持っています。今回はcert-botコンテナも併用し、サーバ証明書を取得してDifyをHTTPSでサービスします。
検証環境¶
| 対象 | バージョン |
|---|---|
| Amazon Linux | 2023.9.20251110 |
| Dify | 1.10.0 |
| Docker | 25.0.13, build 0bab007 |
| Docker Compose | 2.40.3 |
EC2仮想マシンの作成¶
EC2上にDifyを動作させる仮想マシンを作成します。
サイジング¶
Docker Compose デプロイには以下の記載があります。
Dify インストール前に, マシンが最小インストール要件を満たしていることを確認してください:
- CPU >= 2 Core
- RAM >= 4 GiB
これを踏まえ、今回はt4g.mediumな仮想マシンを作成しました。OSにはAmazon Linux 2023を選択しました。
| インスタンスサイズ | vCPU | メモリ (GiB) | ベースラインパフォーマンス/vCPU | CPU クレジット取得/時間 | ネットワークバースト幅 (Gbps) | EBS バースト幅 (Mbps) |
|---|---|---|---|---|---|---|
| t4g.nano | 2 | 0.5 | 5% | 6 | 最大 5 | 最大 2,085 |
| t4g.micro | 2 | 1 | 10% | 12 | 最大 5 | 最大 2,085 |
| t4g.small | 2 | 2 | 20% | 24 | 最大 5 | 最大 2,085 |
| t4g.medium | 2 | 4 | 20% | 24 | 最大 5 | 最大 2,085 |
| t4g.large | 2 | 8 | 30% | 36 | 最大 5 | 最大 2,780 |
| t4g.xlarge | 4 | 16 | 40% | 96 | 最大 5 | 最大 2,780 |
| t4g.2xlarge | 8 | 32 | 40% | 192 | 最大 5 | 最大 2,780 |
セキュリティ要件¶
セキュリティグループではHTTP(TCP/80)とHTTPS(TCP/443)を許可しておきます。
| プロトコル | ポート | 用途 |
|---|---|---|
| TCP | 80 | Let's Encryptでサーバ証明書を取得する際に利用する |
| TCP | 443 | Dify自体のサービスに利用する |
DockerとDocker Composeのインストール¶
DifyはDockerコンテナとして動作させる為、DockerとDocker Composeをインストールします。
Dockerのインストール¶
Dockerはdnfでインストールします。
dnf install -y docker
インストールが完了しました。インストール直後はサービスが停止していました。
# systemctl status docker.service
○ docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: disabled)
Active: inactive (dead)
TriggeredBy: ○ docker.socket
Docs: https://docs.docker.com
サービスを有効化しておきます。
systemctl enable --now docker
Docker Composeのインストール¶
Docker CompsoeのGitHubリポジトリからバイナリを取得してインストールします。
mkdir -p /usr/local/lib/docker/cli-plugins/ && \
curl -SL https://github.com/docker/compose/releases/download/v2.40.3/docker-compose-linux-armv7 -o /usr/local/lib/docker/cli-plugins/docker-compose && \
chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
Difyのインストール¶
gitのインストール¶
GitHubからDifyを取得する為、gitをインストールします。
dnf install -y git
Difyのインストール¶
GitHubからDifyをクローンします。
cd /opt && \
git clone https://github.com/langgenius/dify.git
Difyの設定ファイルはdify/docker/.envですが、このファイルは初期状態だと存在しません。サンプルファイルであるdify/docker/.env.exampleをコピーして作成します。
cd dify/docker && \
cp .env.example .env
基本的な初期設定(コンソールURL、タイムゾーン、メール送信)¶
docker composeで起動したDifyからSMTPでメール送信するの内容に従ってコンソールWeb URLやタイムゾーン、電子メールの送信設定を.envへ設定します。尚、詳細はDify公式の環境変数の説明ページで説明されています。
sed -i -e "s/^CONSOLE_API_URL=/CONSOLE_API_URL=https:\/\/dify.example.com/g" .env
sed -i -e "s/^CONSOLE_WEB_URL=/CONSOLE_WEB_URL=https:\/\/dify.example.com/g" .env
sed -i -e "s/^SERVICE_API_URL=/SERVICE_API_URL=https:\/\/dify.example.com/g" .env
sed -i -e "s/^APP_API_URL=/APP_API_URL=https:\/\/dify.example.com/g" .env
sed -i -e "s/^APP_WEB_URL=/APP_WEB_URL=https:\/\/dify.example.com/g" .env
sed -i -e "s/^LOG_TZ=UTC/LOG_TZ=Asia\/Tokyo/g" .env
sed -i -e "s/^MAIL_TYPE=resend/MAIL_TYPE=smtp/g" .env
sed -i -e "s/^MAIL_DEFAULT_SEND_FROM=/MAIL_DEFAULT_SEND_FROM=no-reply@example.com/g" .env
sed -i -e "s/^SMTP_SERVER=/SMTP_SERVER=email-smtp.us-east-1.amazonaws.com/g" .env
sed -i -e "s/^SMTP_PORT=465/SMTP_PORT=587/g" .env
sed -i -e "s/^SMTP_USERNAME=/SMTP_USERNAME=12345678901234567890/g" .env
sed -i -e "s/^SMTP_PASSWORD=/SMTP_PASSWORD=12345678901234567890123456789012345678901234/g" .env
sed -i -e "s/^SMTP_OPPORTUNISTIC_TLS=false/SMTP_OPPORTUNISTIC_TLS=true/g" .env
設定が完了したら以下を実行し、意図した値に設定されていることを確認します。今回、TRIGGER_URLは設定していないのですが、念の為確認しています。
grep \
-e ^CONSOLE_API_URL= \
-e ^CONSOLE_WEB_URL \
-e ^SERVICE_API_URL= \
-e ^TRIGGER_URL= \
-e ^APP_API_URL= \
-e ^APP_WEB_URL= \
-e ^LOG_TZ \
-e ^MAIL_TYPE \
-e ^MAIL_DEFAULT_SEND_FROM \
-e ^SMTP_SERVER= \
-e ^SMTP_PORT \
-e ^SMTP_USERNAME \
-e ^SMTP_PASSWORD \
-e ^SMTP_USE_TLS \
-e ^SMTP_OPPORTUNISTIC_TLS \
.env
サーバ証明書の取得¶
Difyでサーバ証明書を取得する方法はLaunching new servers with SSL certificatesに記載されています。まず、サーバ証明書の取得に必要なパラメータを.envへ設定します。NGINX_SSL_CERT_FILENAMEとNGINX_SSL_CERT_KEY_FILENAMEはデフォルトのままだと証明書の取得までは成功するのですが、最終的にDifyを起動した際、フロント側を処理するNginxの起動に失敗するようです。
sed -i -e "s/^NGINX_SSL_CERT_FILENAME=dify.crt/NGINX_SSL_CERT_FILENAME=fullchain.pem/g" .env
sed -i -e "s/^NGINX_SSL_CERT_KEY_FILENAME=dify.key/NGINX_SSL_CERT_KEY_FILENAME=privkey.pem/g" .env
sed -i -e "s/^NGINX_ENABLE_CERTBOT_CHALLENGE=false/NGINX_ENABLE_CERTBOT_CHALLENGE=true/g" .env
sed -i -e "s/^CERTBOT_DOMAIN=your_domain.com/CERTBOT_DOMAIN=dify.example.com/g" .env
sed -i -e "s/^CERTBOT_EMAIL=your_email@example.com/CERTBOT_EMAIL=dify@example.com/g" .env
設定が完了したら以下を実行し、意図した値に設定されていることを確認します。
grep \
-e NGINX_HTTPS_ENABLED \
-e NGINX_SSL_CERT_FILENAME \
-e NGINX_SSL_CERT_KEY_FILENAME \
-e NGINX_ENABLE_CERTBOT_CHALLENGE \
-e CERTBOT_EMAIL \
-e CERTBOT_DOMAIN \
.env
docker network pruneで未使用のネットワークを削除したらcertbotプロファイルを指定して起動します。
docker network prune --force && \
docker compose --profile certbot up --force-recreate -d
しばらく待機してコンテナが起動したら以下を実行し、サーバ証明書を取得します。この際、TCP/80ポートが閉塞しているとサーバ証明書の取得に失敗します。
docker compose exec -it certbot /bin/sh /update-cert.sh
サーバ証明書が取得できたらDifyのフロント画面を提供しているNginxがサーバ証明書を利用するように設定します。
sed -i -e "s/^NGINX_HTTPS_ENABLED=false/NGINX_HTTPS_ENABLED=true/g" .env
設定が完了したら再度以下を実行し、意図した値に設定されていることを確認します。
grep \
-e NGINX_HTTPS_ENABLED \
-e NGINX_SSL_CERT_FILENAME \
-e NGINX_SSL_CERT_KEY_FILENAME \
-e NGINX_ENABLE_CERTBOT_CHALLENGE \
-e CERTBOT_EMAIL \
-e CERTBOT_DOMAIN \
.env
これでサーバ証明書の設定は完了です。設定を変更したのでNginxだけ、再起動します。但し後述しますが、この状態ではベクトルデータベースは起動しておらず、Dify自体は利用できるものの、ナレッジベースの作成ができません。
docker compose --profile certbot up -d --no-deps --force-recreate nginx
Webブラウザでhttps://dify.example.com(環境にあわせて読み替えます)にアクセスし、Difyのセットアップ画面が表示されれば成功です。

サーバ証明書の更新¶
自動的にサーバ証明書が更新されるように設定します。Amazon Linux 2023はsystemdベースであり、且つ、デフォルトではcronがインストールされていません。その為、サーバ証明書を更新するタスクはsystemdで設定します。cert-renew.serviceとcert-renew.timerを以下の内容で新規作成します。
| /etc/systemd/system/cert-renew.service | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
| /etc/systemd/system/cert-renew.timer | |
|---|---|
1 2 3 4 5 6 7 8 9 10 | |
タイマーを開始すれば設定完了です。
systemctl daemon-reload && \
systemctl enable --now cert-renew.timer
ベクトルデータベースを起動する¶
ここまでの手順を実行するとコンテナは以下の状態になっていました。DifyはデフォルトだとベクトルデータベースとしてWeaviateを利用しますが、以下のコンテナ一覧にはWeaviateが存在しません。
# docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-api-1 langgenius/dify-api:1.10.0 "/bin/bash /entrypoi…" api 3 minutes ago Up 2 minutes 5001/tcp
docker-certbot-1 certbot/certbot "/docker-entrypoint.…" certbot 3 minutes ago Up 2 minutes 80/tcp, 443/tcp
docker-db-1 postgres:15-alpine "docker-entrypoint.s…" db 3 minutes ago Up 2 minutes (healthy) 5432/tcp
docker-nginx-1 nginx:latest "sh -c 'cp /docker-e…" nginx 36 seconds ago Up 24 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp
docker-plugin_daemon-1 langgenius/dify-plugin-daemon:0.4.1-local "/bin/bash -c /app/e…" plugin_daemon 3 minutes ago Up 2 minutes 0.0.0.0:5003->5003/tcp, [::]:5003->5003/tcp
docker-redis-1 redis:6-alpine "docker-entrypoint.s…" redis 3 minutes ago Up 2 minutes (healthy) 6379/tcp
docker-sandbox-1 langgenius/dify-sandbox:0.2.12 "/main" sandbox 3 minutes ago Up 2 minutes (healthy)
docker-ssrf_proxy-1 ubuntu/squid:latest "sh -c 'cp /docker-e…" ssrf_proxy 3 minutes ago Up 2 minutes 3128/tcp
docker-web-1 langgenius/dify-web:1.10.0 "/bin/sh ./entrypoin…" web 3 minutes ago Up 2 minutes 3000/tcp
docker-worker-1 langgenius/dify-api:1.10.0 "/bin/bash /entrypoi…" worker 3 minutes ago Up 2 minutes 5001/tcp
docker-worker_beat-1 langgenius/dify-api:1.10.0 "/bin/bash /entrypoi…" worker_beat 3 minutes ago Up 2 minutes 5001/tcp
ベクトルデータベースも起動したい場合は特にプロファイルを指定せず、コンテナを再起動します。
docker compose down
docker compose up -d
これでWeaviateも起動しました。
# docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-api-1 langgenius/dify-api:1.10.0 "/bin/bash /entrypoi…" api About a minute ago Up About a minute 5001/tcp
docker-certbot-1 certbot/certbot "/docker-entrypoint.…" certbot 7 minutes ago Up 6 minutes 80/tcp, 443/tcp
docker-db-1 postgres:15-alpine "docker-entrypoint.s…" db 7 minutes ago Up 6 minutes (healthy) 5432/tcp
docker-nginx-1 nginx:latest "sh -c 'cp /docker-e…" nginx 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp
docker-plugin_daemon-1 langgenius/dify-plugin-daemon:0.4.1-local "/bin/bash -c /app/e…" plugin_daemon About a minute ago Up About a minute 0.0.0.0:5003->5003/tcp, [::]:5003->5003/tcp
docker-redis-1 redis:6-alpine "docker-entrypoint.s…" redis 7 minutes ago Up 6 minutes (healthy) 6379/tcp
docker-sandbox-1 langgenius/dify-sandbox:0.2.12 "/main" sandbox 7 minutes ago Up 6 minutes (healthy)
docker-ssrf_proxy-1 ubuntu/squid:latest "sh -c 'cp /docker-e…" ssrf_proxy 7 minutes ago Up 6 minutes 3128/tcp
docker-weaviate-1 semitechnologies/weaviate:1.27.0 "/bin/weaviate --hos…" weaviate About a minute ago Up About a minute
docker-web-1 langgenius/dify-web:1.10.0 "/bin/sh ./entrypoin…" web 7 minutes ago Up 6 minutes 3000/tcp
docker-worker-1 langgenius/dify-api:1.10.0 "/bin/bash /entrypoi…" worker About a minute ago Up About a minute 5001/tcp
docker-worker_beat-1 langgenius/dify-api:1.10.0 "/bin/bash /entrypoi…" worker_beat About a minute ago Up About a minute 5001/tcp
参考¶
cert-botコンテナに含まれている「サーバ証明書を取得・更新するスクリプト」(/update-cert.sh)は以下の内容でした。
| /update-cert.sh | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |