Problemas con Letsencrypt

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.

1 me gusta

simplemente agrega tu dirección de correo electrónico en el archivo de configuración.

/var/discourse/containers/app.yml

## Si agregaste la plantilla de Lets Encrypt, descomenta lo siguiente para obtener un certificado SSL gratuito
 LETSENCRYPT_ACCOUNT_EMAIL: gavin@truecode.co.za

ejecuta ./launcher rebuild app

luego deberías estar listo para comenzar.

Corregimos esto hace un par de semanas, ¿probaste hacer una reconstrucción?

3 Me gusta

No, no lo he hecho. Estoy ejecutando la versión 2.8.0.beta4 y me indica que estoy actualizado. ¿Debo realizar una reconstrucción después de las actualizaciones, o se descargan elementos sobre la marcha entre actualizaciones que requieran una reconstrucción? Sí tengo una dirección de correo electrónico configurada en LETSENCRYPT_ACCOUNT_EMAIL.

Puedo hacer una reconstrucción. Tendré que restaurar primero la versión original del script de letsencrypt, o ¿la reconstrucción lo actualizará automáticamente? ¿Se supone que debo hacer una reconstrucción después de cada actualización, o existe algún método para notificarme cuándo es necesario? Hasta la fecha, nunca he realizado una reconstrucción después de montar el sitio inicialmente hace unos seis meses, aunque he estado aplicando actualizaciones.

Aunque puedes actualizar la aplicación desde la interfaz web, de vez en cuando debemos lanzar una actualización del entorno subyacente en el que se ejecuta Discourse (la imagen del contenedor). Estas actualizaciones del entorno requieren una reconstrucción.

Para deshacer tus cambios locales, es posible que puedas guardarlos temporalmente con:

cd /var/discourse
git stash
./launcher rebuild app
1 me gusta

¿Son estas “actualizaciones ambientales” las actualizaciones de “docker-manager” que veo después de hacer clic en el enlace “realizar actualizaciones aquí” en la página de configuración de administración? Supongo que ahora estoy un poco confundido sobre qué actualizaciones debo obtener, de dónde y cuándo sé que debo hacer una reconstrucción. Aunque veo una actualización en esa página, la página anterior sigue diciendo que estoy al día.

No, para obtenerlas debes acceder al servidor mediante la línea de comandos y ejecutar un rebuild.

De acuerdo. He realizado la reconstrucción, pero no estoy seguro de que funcione en 90 días, ya que el certificado aún no ha expirado, por lo que no está intentando obtener uno nuevo. Verifiqué el script de Let’s Encrypt y muestra una fecha de modificación reciente (hoy), pero al compararlo con la versión anterior del script (la original, no después de mis modificaciones), son idénticos. Intenté ejecutar el script manualmente desde dentro del contenedor usando la opción --force, según lo indicado en uno de los comentarios de los mensajes de salida, pero no funcionó. Por lo tanto, en este punto solo tendré que confiar en que, cuando el certificado expire, se renovará correctamente.