Necesito ayuda con contenedor dual. Problema con LetsEncrypt desde hace unos días

Estoy llegando a un punto de desesperación, porque intentar que el Bot de Discourse o Claude solucionen este problema parece imposible. No puedo explicar bien el problema, ya que no tengo mucho conocimiento al respecto, y creo que eso es lo que realmente me frustra.

Intentaré explicar lo que sucedió desde mi punto de vista.

Cuando estaba migrando de un contenedor único a dos contenedores, el archivo en samples/ usaba web-only y, por error, lo dejé así en lugar de usar web_only.

Entonces, debido a eso (creo), mis imágenes no se cargaban, porque se esperaba que un “elemento” apuntara a web_only, pero estaba configurado como web-only. Hice algunos cambios y las imágenes se arreglaron. El problema ahora son los certificados de Let’s Encrypt.

Le pedí al bot que me ayudara a solucionarlo; me dijo que esperara al día siguiente, porque el problema era el límite de tasa de los certificados. El problema se iba a resolver. No lo hizo. Luego le pregunté de nuevo, después le pregunté a Claude, y luego a Claude otra vez… y llevamos toda la semana en este ciclo de “espera hasta mañana a las X horas y se resolverá DEFINITIVAMENTE”. Nunca se resuelve. Ambos dicen: “Oh, lo siento, no debí asumir que se resolvería, probemos esto en su lugar, porque ahora sí se resolverá de verdad”. Y nunca pasa.

El sitio web en sí está en funcionamiento, pero siento que cada vez que quiero reconstruir, algo va a salir mal, y para ser honesto, no quiero depender de parches todo el tiempo.

Claude me dijo que añadiera algo a los hooks en web_only.yml, pero como no se menciona nada por el estilo en las instrucciones proporcionadas aquí en el foro, esperaba otra solución, como… resolver el problema real.

¿Podría alguien ayudarme a averiguar cuál es el problema y dónde se está rompiendo todo? Lo agradecería mucho, porque en este punto es agotador. No el trabajo en sí, sino no entender qué está pasando y por qué “esperar hasta mañana” nunca parece arreglar nada.

¡Gracias!


Le pedí a Claude que explicara cuál parece ser el problema, quizás eso ayude. Esto es lo que dijo:

Título: Configuración de dos contenedores: falta la carpeta de certificados ECC tras la división, el bucle --force agota el límite de tasa en cada arranque

Configuración: Dos contenedores (data + web_only), migrados de standalone. Plantillas: web, ratelimited, ssl, letsencrypt, cloudflare. Nombre de host alltiago.com, sin alias.

Síntoma: Cada inicio de web_only agota el límite de tasa de Let’s Encrypt y nginx falla al servir, devolviendo errores de conexión hasta que las líneas ECC se eliminan manualmente de /etc/nginx/conf.d/outlets/server/20-https.conf.

Lo que encontré:

/shared/letsencrypt/alltiago.com_ecc/ no existe en mi instalación. /shared/letsencrypt/alltiago.com/ (RSA) existe y funciona bien, renovándose normalmente.

En web.letsencrypt.ssl.template.yml:

cert_exists() {
  [[ "$(cd ${LETSENCRYPT_DIR}/${DISCOURSE_HOSTNAME}$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")" ]]
}

issue_cert "ec-256"
if ! cert_exists "_ecc"; then
  issue_cert "ec-256" "--force"
fi

Dado que la carpeta no existe, cert_exists "_ecc" falla en cada arranque, por lo que se ejecuta --force y solicita un nuevo certificado ECC, independientemente de lo que haya en el disco. Esto es a través del hook after_ssl que parchea /etc/runit/1.d/install-ssl, por lo que se ejecuta en cada inicio del contenedor, no solo en el bootstrap.

Resultado: error 429 too many certificates (5) already issued for this exact set of identifiers in the last 168h. Luego --installcert se ejecuta de todos modos contra la carpeta vacía y escribe un /shared/ssl/alltiago.com_ecc.cer inutilizable. nginx está configurado con ambos certificados, no puede cargar el ECC y no sirve el contenido.

Confirmado que funciona: La validación ACME HTTP-01 tiene éxito (probado vía staging, el certificado ECC se emitió correctamente contra letsencrypt_test, se creó la estructura de directorios correcta). El certificado RSA se renovó con éxito hoy. Así que esto no es un problema de DNS, firewall o validación.

Preguntas:

  1. ¿Hay una forma soportada de recrear alltiago.com_ecc/ sin esperar a que pase el límite de tasa?
  2. ¿Debería cert_exists devolviendo falso realmente desencadenar --force en lugar de una emisión normal? --force omite la comprobación de “certificado válido existente” y garantiza el agotamiento del límite de tasa cuando la carpeta no existe.
  3. ¿Hay una forma documentada de ejecutar solo con RSA?

Dos notas factuales para que el hilo no se desvíe: la fecha de reintento pasó del 27 de agosto al 29 de agosto porque la renovación RSA de hoy consumió un cupo en la ventana móvil de 168 horas. Y la razón por la que nadie más reporta esto es que en una instalación normal ambos directorios se crean en el primer arranque y la rama --force nunca se ejecuta.

Espera. https://alltiago.com/ parece estar funcionando perfectamente. Pero esto es lo que iba a recomendar

Sí, pero es complicado. Si solicitas un certificado DIFERENTE, puedes reiniciar tu contador desde cero.

Lo que probablemente recomendaría es añadir www al nombre de host para obtener certificados para ambos (pero tal vez ya lo hayas hecho, en cuyo caso podrías añadir un tercer nombre, solo para obtener un certificado nuevo).

Set up Let’s Encrypt with multiple domains / redirects debería ayudar.

Sí, es así, porque me indicaron que usara un «parche» relacionado con nginx. No puedo explicarlo realmente, porque no lo entiendo.
Pero el problema es que si luego quiero hacer una reconstrucción normal, tendré problemas (al menos, según me dijeron, si lo hago antes del 29 de agosto, cuando, se espera, se reemita el certificado. En este punto, no puedo confiar del todo en nada de eso.

Sí, www ya está ahí desde que instalé Discourse por primera vez el año pasado.

Ahora, después de exigirle a Claude que diera lo mejor de sí para ayudarme a entender qué está pasando, esto es lo que obtuve, y siéntanse libres de cuestionarlo, porque estoy aquí para aprender cuando es posible:

  • ECC, que parece ser el problema ahora, no es realmente necesario, porque RSA es el predeterminado y todos seguirán accediendo a mi sitio web sin problemas, si elimino por completo ECC.
  • Como dije, se espera que, el 29 de agosto, todo este problema desaparezca, una vez que se restablezcan las 168 horas y también se restablezca el límite de 5 certificados:
sudo docker exec web_only grep -i "retry after" /shared/letsencrypt/acme.sh.log | tail -1
  "detail": "too many certificates (5) already issued for this exact set of identifiers in the last 168h0m0s, retry after 2026-08-29 03:43:15 UTC: see https://letsencrypt.org/docs/rate-limits/#new-certificates-per-exact-set-of-identifiers",
  • Si el 29 de agosto las cosas no vuelven a la normalidad, Claude recomienda eliminar ECC. Esto es lo que dijo cuando le pregunté qué archivo se modificaría y qué sección:

Archivo: la copia que estamos a punto de hacer, web.letsencrypt.rsa-only.template.yml (dejando tu archivo original intacto como respaldo).

Lo que se elimina dentro de él: este bloque completo, encontrado en la sección /usr/local/bin/letsencrypt del archivo:

########################################################
# 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}" ${LETSENCRYPT_DIR}/acme.sh \
  --installcert --ecc \
  -d ${DISCOURSE_HOSTNAME} \
  --fullchainpath /shared/ssl/${DISCOURSE_HOSTNAME}_ecc.cer \
  --keypath /shared/ssl/${DISCOURSE_HOSTNAME}_ecc.key \
  --reloadcmd "sv reload nginx"

Esa es la sección completa de ECC, nada más en el archivo cambia. La sección de RSA justo encima permanece exactamente igual.

Un archivo más se modifica después de eso: containers/web_only.yml, para que apunte a esta nueva copia en lugar de la plantilla estándar. Haremos eso como un paso separado y posterior.

Sí. No. No cambiaría ninguna plantilla.

Supongo que la forma más fácil es esperar y luego reconstruir con las plantillas predeterminadas. A menos que quieras recibir soporte de la IA en lugar de de cualquier otra persona que sepa usar Discourse para siempre.

Le pedí a Claude que siguiera tu consejo añadiendo www como una nueva solicitud de certificado (¿así se llama?). Parece que ahora está funcionando.

Cuando pregunté qué archivos son restos de todo este proceso, recibí esto:

Aquí está lo que hay realmente, dividido entre lo de esta noche y los restos más antiguos de antes de esta conversación:

De esta noche (esta sesión):

  • /tmp/acme.sh.txt — la copia del script que pediste descargar, es seguro eliminarla ahora que lo tienes en tu Mac.
  • /tmp/crtsh.json — archivo vacío de 150 bytes debido al error 502 de crt.sh, basura, es seguro eliminarlo.
  • /root/discourse-backup-20260827-1857.tar.gz — la copia de seguridad real de esta noche (configuraciones de SSL/letsencrypt), esta sí vale la pena conservarla, no es basura.

Más antiguos, de antes de esta conversación (23 y 25 de agosto), no es algo que yo haya puesto ahí:

  • /tmp/app.yml
  • /tmp/check.png, /tmp/check162.png, /tmp/after.png, /tmp/rendered_avatar.png

No sé para qué son esos archivos más antiguos, son anteriores a cualquier cosa que hicimos esta noche, probablemente restos de una sesión de solución de problemas anterior (tuya, del bot o de un chat previo con Claude). ¿Los reconoces o quieres que te ayude a averiguar de dónde son antes de decidir si se eliminan?

No apareció nada sospechoso fuera de /tmp y /root, el escaneo general del sistema salió limpio, solo archivos de registro normales.


¿Puedo proceder a eliminar todos esos?

¿Debería entonces revertir lo que acabo de hacer?

No me molesta en absoluto hablar con personas reales, pero simplemente no quiero hacer todas las preguntas aquí e inundar el foro con todo el proceso (salidas/registros de Terminal), y prefiero llegar con algo que ya esté “más o menos” funcionando para hacer la conversación un poco más corta. Todos tenemos nuestras propias vidas y tiempo limitado, y no quiero ir directamente al foro de inmediato, a menos que realmente me quede atascado, ¿sabes?

¡Agradezco tu ayuda!
Entonces, ¿ahora mismo debería revertir lo que hice? ¿Ves algún problema con ese enfoque en comparación con simplemente esperar al día 29?