Dify (Docker) の Let's Encrypt による HTTPS 通信を有効化する

# はじめに
LLMを活用するのにDifyの活用を試しています。

https://qiita.com/k-kariya/items/1e6540703ffd601907c7

ローカル環境にデプロイ済みのDifyを、インターネットから利用できるように、Let's Encryptによる設定を行いました。基本は公式に書いてある通りなのですが、日本語情報は2025年1月13日現在なさそうなのと、そのままではエラーで進めない部分がありました。

https://github.com/langgenius/dify/blob/main/docker/certbot/README.md

# 環境
- Dify_ 0.9.1
- Windows11

筆者はNoIPのサブドメインを利用しています。
Difyのバージョンが最新ではないため、ドキュメント通り動かなかっただけかも。先にバージョンアップがベターと思われます。

# 手順

##  1. 環境設定ファイル（.env）の編集:
Difyのdockerディレクトリ内にある.envファイルを開き、以下の項目を設定します。
```:.env
NGINX_SSL_CERT_FILENAME=fullchain.pem
NGINX_SSL_CERT_KEY_FILENAME=privkey.pem
NGINX_ENABLE_CERTBOT_CHALLENGE=true
CERTBOT_DOMAIN=your_domain.com
CERTBOT_EMAIL=example@your_domain.com
```
※ CERTBOT_DOMAINにはご自身のドメイン名を、CERTBOT_EMAILには有効なメールアドレスを入力してください。

## 2. Dockerネットワークの整理:
コマンドプロンプトを開き、以下のコマンドを実行して不要なネットワークを削除します。
```batchfile
docker network prune
```
警告が出ますが、続行させます。さ     
## 3. Certbotプロファイルでのコンテナ起動:
以下のコマンドを実行して、Certbotプロファイルを有効にした状態でコンテナを再作成・起動します。
```batchfile
docker compose --profile certbot up --force-recreate -d
```
     
## 4. SSL証明書の取得:
Certbotコンテナ内で証明書を取得するため、以下のコマンドを実行します。
```batchfile
docker compose exec -it certbot /bin/sh /update-cert.sh
```
これはエラー `/update-cert.sh: set: line 2: illegal option -` となってしまいました。

2行目のオプションが正しくないというエラーですが、改行コードをWindows標準のCR+LFからUnix標準のLFに変更することで解消しました。

:::note info
Docker環境に入って実行することで取得できる場合がありました。
Docker環境に入る
```batchfile
docker compose exec -it certbot /bin/sh
```
update-cert.shを実行
``` sh
cd /
sh update-cert.sh
```
:::

:::note info
SSL証明書の取得で次のエラーが出る場合は下記の確認も行います
    Certbot failed to authenticate some domains (authenticator: webroot).
    （中略）Timeout during connect (likely firewall problem)
    - サーバーのファイアウォールで80番、443番ポートが解放されているか
    - ルーターでポートフォワーディングの設定が行われ、有効になっているか
    - LANへの接続はプライベートになっているか
:::

## 5. HTTPSの有効化:
.envファイルの設定を変更し、Nginxコンテナを再起動します。
```:.env
NGINX_HTTPS_ENABLED=true
```
```batchfile
docker compose --profile certbot up -d --no-deps --force-recreate nginx
```

## 6. Nginxの設定ファイルの確認・設定追加（１）HTTPS通信有効化

まずはHTTPS通信ができるようにします。
上記設定でHTTPS通信が可能のようなのですが、今回は以下の設定が必要でした。
/etc/nginx/conf.d/default.conf の設定を確認します。
インストールしたフォルダの dify\docker\nginx\conf.d にあるファイルを編集します。(docker-compose.yamlでマウントされているフォルダを確認できます)
    
```/etc/nginx/conf.d/default.conf
server {
    listen 443 ssl;
    server_name your_domain.com;

    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:80; # 内部アプリのポートに適宜変更
    }
}
```
Nginxを再起動
```batchfile
docker compose exec nginx nginx -s reload
```
これでHTTPS通信が有効化されているはずです。https://your_domain.com/へブラウザでアクセスしてみてください。

## 7. Nginxの設定ファイルの確認・設定追加（２）HTTPｋHTTPS通信へのリダイレクトの設定

続いて、http://your_domain.com/への接続もHTTPS通信に自動でリダイレクトする設定を追加します。
先ほど編集したdefault.confに次の設定を追加します。

```/etc/nginx/conf.d/default.conf
server {
    listen 80;
    server_name your_domain.com;

    # リダイレクト設定を追加
    location / {
        return 301 https://$host$request_uri;
    }

    # placeholder for acme challenge location
    location /.well-known/acme-challenge/ { 
        root /var/www/html;
    }
}
```
Nginxを再起動
```batchfile
docker compose exec nginx nginx -s reload
```
これで http://your_domain.com/へブラウザでアクセスしても、https://your_domain.com/へリダイレクトされるため、より安全なサーバー利用が可能となります。

:::note info
NoIPなどDDNSサービスを利用しているサーバーの場合でも、your_domain.comのところを、your_subdomain.ddns.netに読み替えて設定できます。
:::
:::note info
独自ドメインがあれば、DNSレコードの設定でCNAMEのレコードを追加することで、独自ドメインのURLでDDNSを利用している自前Difyサーバーを呼び出すことも可能です。
DNSレコード： `dify.your_domain.com` `CNAME` `your_subdomain.ddns.net`
```/etc/nginx/conf.d/default.conf
server {
    listen 80;
    server_name your_subdomain.ddns.net dify.your_domain.com;
    (中略)
}
server {
    listen 443 ssl;
    server_name your_subdomain.ddns.net dify.your_domain.com;
    (中略)
}
```
:::

## 証明書の自動更新
Certbotが証明書の自動更新を行ってくれるはずですが、念のための確認方法など。

現在の証明書の有効期限を確認します。
```bash
docker compose exec certbot certbot certificates
```
手動で更新する場合は以下のコマンドを実行します。
```bash
docker compose exec certbot certbot renew --force-renewal
docker compose restart nginx
```


# おわりに
DifyにCertbotを設定し、HTTPS通信できるようになりました。
残課題としてはユーザ管理やRAGの高度化など・・・
勉強しながら進めていきたいと思います。
ありがとうございました。