Aparentemente, el servicio de Let’s Encrypt experimentó algunos cambios a partir del 1 de agosto. Mi certificado no vencía hasta hoy, por lo que solo me vi afectado por los cambios en la fecha de hoy. Los scripts que Discourse utiliza para gestionar el servicio de Let’s Encrypt se actualizaron para usar por defecto un nuevo servicio llamado ZeroSSL en lugar de Let’s Encrypt. Desafortunadamente, ZeroSSL parece requerir registro con una dirección de correo electrónico antes de funcionar, así que esta mañana, cuando mi certificado existente expiró, el sitio dejó de funcionar.
Después de bastante investigación, logré identificar el problema. Aunque he logrado sortearlo, no creo que lo que hice para solucionarlo sea necesariamente la “solución correcta”. Primero, aquí están los mensajes de error que aparecían en el registro:
[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
Intenté registrar manualmente la cuenta desde dentro del contenedor y, aunque indicó que se había registrado, al reiniciar el contenedor obtuve el mismo error. Entonces rastree los scripts y el que realiza esta acción se encuentra dentro del contenedor en /etc/runit/1.d/letsencrypt. Aquí está el script original:
#!/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
Como el registro con correo electrónico no funcionó, decidí añadir la opción para que el script de acme.sh volviera a usar el Let’s Encrypt original en lugar de ZeroSSL. Las instrucciones sobre cómo hacerlo se proporcionaron en este sitio web: https://community.letsencrypt.org/t/the-acme-sh-will-change-default-ca-to-zerossl-on-august-1st-2021/144052
Primero intenté añadir esto como la tercera línea del script, justo después de la instrucción “/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf”:
/shared/letsencrypt/acme.sh --set-default-ca --server letsencrypt
El registro mostró un mensaje indicando que el valor predeterminado había cambiado, pero inmediatamente después recibí el mismo error sobre la falta de registro de correo electrónico para ZeroSSL. Hubo un retraso de aproximadamente 6 segundos en el registro entre ese mensaje y los mensajes de error, lo que me lleva a pensar que el script de acme.sh debe estar manteniendo información de estado a través de variables de entorno y que las ejecuciones posteriores del comando se estaban ejecutando en un contexto diferente, perdiendo así la variable. Por lo tanto, lo que terminé teniendo que hacer fue cambiar todas las invocaciones de acme.sh en el script de letsencrypt para añadir este operando al comando: “–server letsencrypt”. Cuando hice eso y reinicié el contenedor, se generó un nuevo certificado por Let’s Encrypt en lugar de ZeroSSL y el sitio volvió a funcionar.
Aquí está la versión modificada del script de letsencrypt que utilicé:
#!/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
También dejé el comando original que había insertado para intentar establecer el servicio predeterminado, por si acaso, aunque puede que no sea necesario.
Por lo tanto, lo que debe suceder es que este script debe modificarse para: definir explícitamente el servicio de Let’s Encrypt que se utilizará en todas las invocaciones de acme.sh; o averiguar cómo acme.sh guarda la información de estado para que una única invocación del comando predeterminado funcione; o, por último, añadir soporte para ZeroSSL y la necesidad de recopilar y guardar una dirección de correo electrónico.
Asumo que lo que hice será sobrescrito la próxima vez que actualice las versiones y tendré que hacerlo de nuevo si esto no se soluciona.
Si he pasado por alto algo aquí o si esto se abordó de alguna otra manera que no requiera cambiar los scripts, por favor hágamelo saber.