8월 1일부로 letsencrypt 서비스에서 일부 변경 사항이 발생한 것 같습니다. 제 인증서는 오늘까지 유효했기 때문에, 저는 오늘 변경 사항의 영향을 받았습니다. discourse가 letsencrypt 서비스를 관리하는 데 사용하는 스크립트는 기본적으로 letsencrypt 대신 ZeroSSL이라는 새로운 서비스를 사용하도록 업데이트되었습니다. 불행히도 ZeroSSL은 작동하려면 이메일 주소로 등록해야 하는 것 같아서, 오늘 아침 기존 인증서가 만료되었을 때 사이트가 작동하지 않았습니다.
꽤나 많은 조사를 한 끝에 문제를 파악했고, 제 방식으로는 이를 우회했지만, 제가 적용한 수정이 반드시 “올바른” 해결책이라고는 생각하지 않습니다. 먼저, 로그에서 확인했던 오류 메시지는 다음과 같습니다:
[Wed 01 Sep 2021 05:33:58 PM UTC] Reload error for :
[Wed 01 Sep 2021 05:34:03 PM UTC] Using CA: https://acme.zerossl.com/v2/DV90
[Wed 01 Sep 2021 05:34:04 PM UTC] No EAB credentials found for ZeroSSL, let's get one
[Wed 01 Sep 2021 05:34:04 PM UTC] acme.sh is using ZeroSSL as default CA now.
[Wed 01 Sep 2021 05:34:04 PM UTC] Please update your account with an email address first.
[Wed 01 Sep 2021 05:34:04 PM UTC] acme.sh --register-account -m my@example.com
[Wed 01 Sep 2021 05:34:04 PM UTC] See: https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA
[Wed 01 Sep 2021 05:34:04 PM UTC] Please check log file for more details: /shared/letsencrypt/acme.sh.log
컨테이너 내부에서 수동으로 계정을 등록해 보았지만, 등록되었다고 표시되었음에도 컨테이너를 재시작했을 때 동일한 오류가 발생했습니다. 이후 스크립트를 추적해 보니, 이 작업을 수행하는 스크립트는 컨테이너 내부의 /etc/runit/1.d/letsencrypt 위치에 있었습니다. 원본 스크립트는 다음과 같습니다:
#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf
issue_cert() {
LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --issue $2 -d mudtoemanor.baronshire.org --keylength $1 -w /var/www/discourse/public
}
cert_exists() {
[[ "$(cd /shared/letsencrypt/mudtoemanor.baronshire.org$1 && openssl verify -CAfile ca.cer fullchain.cer | grep "OK")" ]]
}
########################################################
# RSA cert
########################################################
issue_cert "4096"
if ! cert_exists ""; then
# Try to issue the cert again if something goes wrong
issue_cert "4096" "--force"
fi
LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
--installcert \
-d mudtoemanor.baronshire.org \
--fullchainpath /shared/ssl/mudtoemanor.baronshire.org.cer \
--keypath /shared/ssl/mudtoemanor.baronshire.org.key \
--reloadcmd "sv reload nginx"
########################################################
# ECDSA cert
########################################################
issue_cert "ec-256"
if ! cert_exists "_ecc"; then
# Try to issue the cert again if something goes wrong
issue_cert "ec-256" "--force"
fi
LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
--installcert --ecc \
-d mudtoemanor.baronshire.org \
--fullchainpath /shared/ssl/mudtoemanor.baronshire.org_ecc.cer \
--keypath /shared/ssl/mudtoemanor.baronshire.org_ecc.key \
--reloadcmd "sv reload nginx"
if cert_exists "" || cert_exists "_ecc"; then
grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
fi
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop
이메일 등록이 작동하지 않아서, ZeroSSL 대신 원래의 letsencrypt를 사용하도록 acme.sh 스크립트를 변경하기로 결정했습니다. 이를 수행하는 방법은 https://community.letsencrypt.org/t/the-acme-sh-will-change-default-ca-to-zerossl-on-august-1st-2021/144052 웹사이트에서 설명하고 있습니다.
먼저, 스크립트의 세 번째 줄, 즉 “/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf” 문 바로 뒤에 다음을 추가해 보았습니다:
/shared/letsencrypt/acme.sh --set-default-ca --server letsencrypt
로그에는 기본값이 변경되었다는 메시지가 표시되었지만, 바로 그 직후 ZeroSSL에 등록된 이메일이 없다는 동일한 오류가 발생했습니다. 해당 메시지와 오류 메시지 사이에 약 6초의 지연이 로그에 기록되었는데, 이는 acme.sh 스크립트가 환경 변수를 통해 상태 정보를 유지하고 있으며, 이후 명령 실행이 다른 컨텍스트에서 이루어져 변수가 유실되었기 때문이라고 추측됩니다. 결국 제가 해야 했던 일은 letsencrypt 스크립트 내의 모든 acme.sh 호출에 “–server letsencrypt” 이라는 옵션을 추가하는 것이었습니다. 이렇게 하고 컨테이너를 재시작하자 ZeroSSL 대신 letsencrypt에 의해 새로운 인증서가 생성되었고 사이트가 다시 작동했습니다.
제가 사용한 수정된 letsencrypt 스크립트 버전은 다음과 같습니다:
#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf
/shared/letsencrypt/acme.sh --set-default-ca --server letsencrypt
issue_cert() {
LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --server letsencrypt --issue $2 -d mudtoemanor.baronshire.org --keylength $1 -w /var/www/discourse/public
}
cert_exists() {
[[ "$(cd /shared/letsencrypt/mudtoemanor.baronshire.org$1 && openssl verify -CAfile ca.cer fullchain.cer | grep "OK")" ]]
}
########################################################
# RSA cert
########################################################
issue_cert "4096"
if ! cert_exists ""; then
# Try to issue the cert again if something goes wrong
issue_cert "4096" "--force"
fi
LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
--installcert \
-d mudtoemanor.baronshire.org \
--fullchainpath /shared/ssl/mudtoemanor.baronshire.org.cer \
--keypath /shared/ssl/mudtoemanor.baronshire.org.key \
--server letsencrypt \
--reloadcmd "sv reload nginx"
########################################################
# ECDSA cert
########################################################
issue_cert "ec-256"
if ! cert_exists "_ecc"; then
# Try to issue the cert again if something goes wrong
issue_cert "ec-256" "--force"
fi
LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
--installcert --ecc \
-d mudtoemanor.baronshire.org \
--fullchainpath /shared/ssl/mudtoemanor.baronshire.org_ecc.cer \
--keypath /shared/ssl/mudtoemanor.baronshire.org_ecc.key \
--server letsencrypt \
--reloadcmd "sv reload nginx"
if cert_exists "" || cert_exists "_ecc"; then
grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
fi
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop
혹시 모르니 기본 서비스를 설정하기 위해 제가 삽입했던 원래 명령도 남겨 두었지만, 이것이 반드시 필요한 것은 아닐 수 있습니다.
따라서 필요한 작업은 이 스크립트를 변경하여 acme.sh의 모든 호출에서 사용할 letsencrypt 서비스를 명시적으로 정의하거나, acme.sh가 상태 정보를 어떻게 저장하는지 파악하여 기본값 설정 명령을 한 번만 실행해도 작동하도록 하거나, 마지막으로 ZeroSSL을 지원하고 이메일 주소를 수집 및 저장하는 기능을 추가하는 것입니다.
이것이 처리되지 않으면 다음 버전 업그레이드 시 제가 한 작업이 덮어써질 것이며, 다시 같은 작업을 해야 할 것이라고 추정합니다.
제가 놓친 부분이 있거나 스크립트 변경 없이 다른 방식으로 해결된 경우 알려 주십시오.