HTTPS化したDifyで証明書を更新する

以下の記事で紹介されているHTTPS対応のDifyで、証明書を更新する手順のメモ。

https://note.com/sangmin/n/n7126d67f2c97

# 1.前提
以下のコマンドを実行することで構築されたHTTPS対応のDify環境で証明書を更新します。

>【追記：2024.08.08】Dify v.0.6.16でCertbotサービスが追加され、HTTPSの設定が自動化できるようになりました。該当マシンにログインし、下記2つのコマンドを実行していただきますと4分程度でHTTPS設定済みのDifyが使えます。
>>curl -fsSL https://bit.ly/3YHdSo0 -o install-dify.sh
sudo sh ./install-dify.sh email domain


上記で実行しているコマンド、
"install-dify.sh"では"update-cert.sh"
>"sudo docker compose -f docker/docker-compose.yaml exec -T certbot /bin/sh /update-cert.sh"

を実行することで、証明書を取得しています。

```install-dify.sh
# Check if email and domain parameters are provided
if [ $# -ne 2 ]; then
    echo "Usage: $0 <email> <domain>"
    exit 1
fi

EMAIL=$1
DOMAIN=$2

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# Clone Dify repository
git clone https://github.com/langgenius/dify.git
cd dify

# Copy .env.example to .env
cp docker/.env.example docker/.env

# Update .env
sed -i 's/^NGINX_SSL_CERT_FILENAME=.*/NGINX_SSL_CERT_FILENAME=fullchain.pem/' docker/.env
sed -i 's/^NGINX_SSL_CERT_KEY_FILENAME=.*/NGINX_SSL_CERT_KEY_FILENAME=privkey.pem/' docker/.env
sed -i 's/^NGINX_ENABLE_CERTBOT_CHALLENGE=.*/NGINX_ENABLE_CERTBOT_CHALLENGE=true/' docker/.env
sed -i "s/^CERTBOT_DOMAIN=.*/CERTBOT_DOMAIN=$DOMAIN/" docker/.env
sed -i "s/^CERTBOT_EMAIL=.*/CERTBOT_EMAIL=$EMAIL/" docker/.env

# Update SERVICE_API_URL and APP_WEB_URL
sed -i "s|^SERVICE_API_URL=.*|SERVICE_API_URL=https://$DOMAIN|" docker/.env
sed -i "s|^APP_WEB_URL=.*|APP_WEB_URL=https://$DOMAIN|" docker/.env

# Prune Docker networks and start containers
sudo docker network prune -f
sudo docker compose -f docker/docker-compose.yaml --profile certbot up --force-recreate -d


# Run certbot
sudo docker compose -f docker/docker-compose.yaml exec -T certbot /bin/sh /update-cert.sh

# Enable HTTPS
sed -i 's/^NGINX_HTTPS_ENABLED=.*/NGINX_HTTPS_ENABLED=true/' docker/.env

# Recreate nginx container
sudo docker compose -f docker/docker-compose.yaml --profile certbot up -d --no-deps --force-recreate nginx

echo "Dify installation with SSL is complete. Please check https://$DOMAIN"
```



# 2.更新について
Certbotによって取得した証明書の期限は90日のため、期限が来た際の更新方法が気になりました。そこでupdate-cert.sh
>"sudo docker compose -f docker/docker-compose.yaml exec -T certbot /bin/sh /update-cert.sh"

を単体で実行した結果が以下の通りです。
"Certificate not yet due for renewal"とあるように期限が来れば更新してくれるようです。他のソースを見るとCertbotは期限が30日を切ればリニューアルをしてくれるようです。

```update-cert.sh実行時のログ
Certificate exists. Attempting to renew...
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/hoge.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificates are not due for renewal yet:
  /etc/letsencrypt/live/hoge.com/fullchain.pem expires on 2024-11-28 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate operation successful
Please ensure to reload Nginx to apply any certificate changes.
```
# 3.(参考)強制的に更新する方法
期限が30日を切るのを待てるのであれば、問題ではありませんが、そうでない場合のために強制的に更新する方法を調べました。

## 強制オプションを付与
"update-cert.sh"は以下の内容です。"certbot renew"を実行していますが、この時に --force-renewalオプションを付ければ有効期限が30日以上あっても更新してくれます（試していないので多分）


```update-cert.sh
#!/bin/bash
set -e

DOMAIN="hoge.com"
EMAIL="hoge@hoge.com"
OPTIONS=""
CERT_NAME="${DOMAIN}" # 証明書名をドメイン名と同じにする

# Check if the certificate already exists
if [ -f "/etc/letsencrypt/renewal/${CERT_NAME}.conf" ]; then
  echo "Certificate exists. Attempting to renew..."
  certbot renew --noninteractive --cert-name ${CERT_NAME} --webroot --webroot-path=/var/www/html --email ${EMAIL} --agree-tos --no-eff-email ${OPTIONS}
else
  echo "Certificate does not exist. Obtaining a new certificate..."
  certbot certonly --noninteractive --webroot --webroot-path=/var/www/html --email ${EMAIL} --agree-tos --no-eff-email -d ${DOMAIN} ${OPTIONS}
fi
echo "Certificate operation successful"
```

## 違う方法
以下のコマンドでashに入ったうえで、、、
>"sudo docker compose -f docker/docker-compose.yaml exec -T certbot /bin/ash"

rm -rfで以下のファイルおよびフォルダを削除したのちにupdate-cert.shを実行することで証明書が更新されました。

```
/etc/letsencrypt/renewal/hoge.com.conf
/etc/letsencrypt/archive/hoge.com
/etc/letsencrypt/live/hoge.com
```

その後、以下のコマンドを実行し、nginxを再起動することでHTTPS通信で使用される証明書が更新されました。
>"sudo docker compose -f docker/docker-compose.yaml --profile certbot up -d --no-deps --force-recreate nginx"