certificados: emitidos, y las dos trampas del camino
www.feadulta.com, feadulta.com y wp-nuevo.feadulta.com, de Let's Encrypt y validos hasta el 1-nov. Ya se puede subir la zona a Full (strict). Lo que funciono es el plan B de Inma, porque la Configuration Rule que propuse primero no se puede montar en su plan de Cloudflare: custom rule del WAF con accion Skip para la ruta del reto, mas apagar Always Use HTTPS a nivel de zona unos minutos. Dos cosas que costaron tiempo y quedan anotadas: acme.json escribe "main": "dominio" CON espacio. Un grep sin espacio da vacio siempre y parece que no hay certificados. Los de hoy llevaban casi una hora emitidos mientras mi bucle de vigilancia informaba de "sin novedad", y por eso lanzamos un reintento que no hacia falta. Va el snippet que parsea el JSON. Y se retira un riesgo que yo mismo habia documentado: el modo Full NO impide el reto. Se temia que Cloudflare mandara la validacion al 443, donde el handler de ACME no existe. Es falso y se midio: con Always Use HTTPS apagado, una peticion HTTP a la ruta del reto a traves de Cloudflare devuelve 404 con 0 bytes y server: cloudflare, o sea que reenvia al puerto 80 y responde Traefik. Mejor quitarlo que dejar una advertencia falsa en un documento que va a leer otra gente. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,8 +20,9 @@ disabled"*.
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 🔴 **Certificados LE de `www` y el apex** | Sin emitir. El WAF de Cloudflare devuelve **403 a la validación** de Let's Encrypt en `/.well-known/acme-challenge/…`. **No bloquea con la zona en `Full`** (Cloudflare acepta el cert por defecto de Traefik), pero **impide subir a `Full (strict)`**. Se arregla con una excepción del WAF para esa ruta, o pasando a validación **DNS-01** con el token que ya tenemos. Traefik no reintenta solo: hará falta un redeploy. |
|
| ✅ **Certificados LE de `www` y el apex** | **Emitidos el 3-ago a las 12:03 UTC**, válidos hasta el 1-nov. Detalle y las dos trampas del camino en `certificados-letsencrypt-cloudflare.md`. **Ya se puede subir la zona a `Full (strict)`.** |
|
||||||
| 🔴 **Backups en Hetzner** | Siguen sin existir. Ahora ahí vive producción, así que ya no es deuda técnica: es el único sitio donde están los datos vivos. |
|
| ✅ **Application passwords** | Wordfence las desactiva por defecto y eso dejaba a los bots sin poder publicar (401 en la REST API). Reactivado y **añadido como paso 3e de `post-import-seguridad.sh`**, porque el 3d reinstala Wordfence y volvería a romperse. |
|
||||||
|
| ✅ **Backups en Hetzner** | Ya existen (verificado por Rafa en otra sesión). |
|
||||||
| 🟡 **CDMON** | Es el rollback. Inma lo está degradando a un plan barato con el correo. Caduca el **07/08**. |
|
| 🟡 **CDMON** | Es el rollback. Inma lo está degradando a un plan barato con el correo. Caduca el **07/08**. |
|
||||||
| 🟡 **`nuevo.feadulta.com`** | Ya no hace falta; retirar el registro cuando se quiera. |
|
| 🟡 **`nuevo.feadulta.com`** | Ya no hace falta; retirar el registro cuando se quiera. |
|
||||||
| 🟡 **Scripts que apuntan a `134.0.10.170` y `/web/`** | Cierra #158. |
|
| 🟡 **Scripts que apuntan a `134.0.10.170` y `/web/`** | Cierra #158. |
|
||||||
|
|||||||
@@ -1,17 +1,59 @@
|
|||||||
# Los certificados de Let's Encrypt de `www` y el apex no se emiten
|
# Los certificados de Let's Encrypt de `www` y el apex
|
||||||
|
|
||||||
**Estado: abierto.** Bloqueado a la espera de una regla en Cloudflare, que gestiona Inma.
|
## ✅ RESUELTO — 3-ago-2026, 12:03 UTC
|
||||||
Fecha: 3-ago-2026, después del cutover. Plan maestro: `rafa/feadulta`#180.
|
|
||||||
|
|
||||||
## Resumen para quien tenga prisa
|
```
|
||||||
|
www.feadulta.com Let's Encrypt YR2 3-ago-2026 -> 1-nov-2026
|
||||||
|
feadulta.com Let's Encrypt YR2 3-ago-2026 -> 1-nov-2026
|
||||||
|
wp-nuevo.feadulta.com Let's Encrypt YR1 3-ago-2026 -> 1-nov-2026
|
||||||
|
```
|
||||||
|
|
||||||
Traefik no consigue el certificado de `www.feadulta.com` ni de `feadulta.com`. **No hay nada roto
|
**Lo que funcionó** (el "plan B" de Inma, porque la Configuration Rule que se propuso primero **no
|
||||||
para los visitantes**: Cloudflare presenta su propio certificado, y hacia el origen —con el modo SSL
|
se puede montar en este plan de Cloudflare**):
|
||||||
de la zona en `Full`— acepta el certificado por defecto de Traefik. El único coste es que **la zona
|
|
||||||
no puede subir a `Full (strict)`** hasta que se resuelva.
|
|
||||||
|
|
||||||
La causa es que el reto HTTP-01 de Let's Encrypt acaba llegando por HTTPS y Cloudflare lo bloquea
|
1. **Custom rule del WAF con acción *Skip*** para `/.well-known/acme-challenge/`.
|
||||||
con un 403. Se arregla con una **Configuration Rule** en Cloudflare acotada a la ruta del reto.
|
2. **Apagar "Always Use HTTPS" a nivel de zona** durante unos minutos, y volver a encenderlo después.
|
||||||
|
|
||||||
|
Con eso el reto se completa por el puerto 80, donde lo atiende Traefik. **Ya se puede subir la zona
|
||||||
|
a `Full (strict)`.**
|
||||||
|
|
||||||
|
### ⚠️ Dos avisos para la próxima, que costaron tiempo
|
||||||
|
|
||||||
|
**1. `acme.json` escribe `"main": "dominio"` CON espacio.** Un `grep '"main":"'` da vacío siempre y
|
||||||
|
parece que no hay certificados. Los certificados de hoy llevaban **casi una hora emitidos** mientras
|
||||||
|
un bucle de vigilancia mal escrito informaba de "sin novedad". **Parsear el JSON, no grepear:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec coolify-proxy cat /traefik/acme.json > /tmp/a.json
|
||||||
|
python3 -c "
|
||||||
|
import json
|
||||||
|
d=json.load(open('/tmp/a.json'))
|
||||||
|
for r,v in d.items():
|
||||||
|
if isinstance(v,dict):
|
||||||
|
for c in (v.get('Certificates') or []): print(c.get('domain',{}).get('main'))
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Se descartó un riesgo que se había anotado aquí: el modo `Full` NO impide el reto.** Se temía
|
||||||
|
que Cloudflare, al hablar con el origen por HTTPS, mandara la validación al 443 —donde el handler de
|
||||||
|
ACME no existe— y que HTTP-01 fuera imposible con la zona en `Full`. **Es falso**, y se midió:
|
||||||
|
con "Always Use HTTPS" apagado, una petición HTTP a la ruta del reto a través de Cloudflare devuelve
|
||||||
|
**404 con 0 bytes y `server: cloudflare`**, es decir, Cloudflare **sí reenvía al puerto 80** y
|
||||||
|
responde el handler de Traefik.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Lo que sigue es el diagnóstico, que se conserva porque explica cómo se llegó hasta aquí y contiene
|
||||||
|
un par de trampas que conviene no repetir.*
|
||||||
|
|
||||||
|
## Resumen del problema (histórico)
|
||||||
|
|
||||||
|
Traefik no conseguía el certificado de `www.feadulta.com` ni de `feadulta.com`. **No había nada roto
|
||||||
|
para los visitantes**: Cloudflare presentaba su propio certificado, y hacia el origen —con el modo
|
||||||
|
SSL de la zona en `Full`— aceptaba el certificado por defecto de Traefik. El único coste era que la
|
||||||
|
zona no podía subir a `Full (strict)`.
|
||||||
|
|
||||||
|
La causa: el reto HTTP-01 acababa llegando por HTTPS y Cloudflare lo bloqueaba con un 403.
|
||||||
|
|
||||||
## Lo que dice Let's Encrypt, que es el único testigo que vale
|
## Lo que dice Let's Encrypt, que es el único testigo que vale
|
||||||
|
|
||||||
@@ -79,33 +121,11 @@ SSL. **La regla no se puede montar así.**
|
|||||||
Es una excepción mínima y acotada: esa ruta no sirve contenido, solo tokens de un solo uso que el
|
Es una excepción mínima y acotada: esa ruta no sirve contenido, solo tokens de un solo uso que el
|
||||||
propio Traefik genera y valida.
|
propio Traefik genera y valida.
|
||||||
|
|
||||||
### ⚠️ Puede que aun así no salga, y conviene saber por qué antes de intentarlo
|
|
||||||
|
|
||||||
Con el modo SSL de la zona en **`Full`, Cloudflare habla con el origen por HTTPS**. Si eso se aplica
|
|
||||||
también a las peticiones que le entran por HTTP, entonces al apagar "Always Use HTTPS" la petición
|
|
||||||
de Let's Encrypt llegará igualmente al **443** de Traefik, donde **el handler de ACME no existe** —y
|
|
||||||
volverá a fallar, ahora con un 404 en vez de un 403.
|
|
||||||
|
|
||||||
No se puede determinar desde aquí sin apagar el ajuste: mientras "Always Use HTTPS" esté encendido,
|
|
||||||
Cloudflare redirige en su borde y **nunca llega a contactar con el origen por el puerto 80**, así que
|
|
||||||
no hay forma de observar qué puerto usaría.
|
|
||||||
|
|
||||||
**Cómo distinguir los dos casos en el siguiente intento**, mirando el error de Traefik:
|
|
||||||
|
|
||||||
| lo que reporte Let's Encrypt | qué significa | qué hacer |
|
|
||||||
|---|---|---|
|
|
||||||
| sale el certificado | Cloudflare reenvía por el 80 y Traefik atiende | nada más |
|
|
||||||
| `403` | el *Skip* del WAF no está cogiendo esa ruta | revisar el ámbito de la regla |
|
|
||||||
| **`404`** | **Cloudflare va al 443 del origen**: HTTP-01 no puede funcionar con la zona en `Full` | **pasar a DNS-01, dejar de quemar validaciones** |
|
|
||||||
|
|
||||||
### Sobre los visitantes durante la ventana
|
### Sobre los visitantes durante la ventana
|
||||||
|
|
||||||
Apagar "Always Use HTTPS" unos minutos es inocuo, pero **no exactamente por el motivo que parece**.
|
Apagar "Always Use HTTPS" unos minutos resultó inocuo: Cloudflare reenvía al puerto 80 del origen y
|
||||||
Si Cloudflare reenviara por el 80, Traefik devuelve un 302 a HTTPS por su cuenta (medido) y el
|
**Traefik devuelve su propio 302 a HTTPS**, así que el visitante acaba en HTTPS igual. Medido antes
|
||||||
visitante acaba igual. Si Cloudflare va al 443, ese 302 no llega a dispararse y **un visitante que
|
y durante.
|
||||||
entre por `http://` se quedará en `http://`** — con el contenido correcto y cifrado hasta Cloudflare,
|
|
||||||
pero sin subir a HTTPS. Para una ventana de minutos no tiene consecuencias, pero que nadie se
|
|
||||||
extrañe si lo ve.
|
|
||||||
|
|
||||||
### Alternativa de fondo, para más adelante
|
### Alternativa de fondo, para más adelante
|
||||||
|
|
||||||
@@ -148,11 +168,8 @@ Cuesta **unos 7 segundos** de corte: se ha medido dos veces, un único 500 y vue
|
|||||||
|
|
||||||
### Comprobar si ya salió
|
### Comprobar si ya salió
|
||||||
|
|
||||||
```bash
|
⚠️ **No con `grep`** — ver el aviso del principio: el fichero escribe `"main": "dominio"` con
|
||||||
docker exec coolify-proxy cat /traefik/acme.json | grep -oE '"main":"[^"]*feadulta[^"]*"'
|
espacio y un patrón sin espacio da vacío siempre. Parsear el JSON.
|
||||||
```
|
|
||||||
|
|
||||||
Hoy sólo aparecen `antiguo.feadulta.com`, `nuevo.feadulta.com` y `gitea.feadulta.com`.
|
|
||||||
|
|
||||||
## Cabo suelto ya cerrado por el camino
|
## Cabo suelto ya cerrado por el camino
|
||||||
|
|
||||||
@@ -161,7 +178,7 @@ cualquier 404. No era la causa —el reto va por el 80 y ahí ni llega a WordPre
|
|||||||
era una trampa para el futuro. Arreglado y desplegado: las rutas de protocolo quedan exentas y el
|
era una trampa para el futuro. Arreglado y desplegado: las rutas de protocolo quedan exentas y el
|
||||||
resto del redirect sigue igual. Lo encontró el Claude de Inma.
|
resto del redirect sigue igual. Lo encontró el Claude de Inma.
|
||||||
|
|
||||||
## Cuando el certificado salga
|
## `Full (strict)`
|
||||||
|
|
||||||
Entonces —y sólo entonces— se puede subir la zona a **`Full (strict)`**, que valida además el
|
Ya se puede: los tres certificados están emitidos. Sube la seguridad porque valida además el
|
||||||
certificado del origen. Hacerlo antes rompe el sitio.
|
certificado del origen. **Comprobar el sitio justo después de cambiarlo.**
|
||||||
|
|||||||
Reference in New Issue
Block a user