Actualiza toolkit operativo y documentación
This commit is contained in:
@@ -31,17 +31,41 @@ de Cloudflare arranquen solos**, sin intervención manual.
|
||||
|
||||
En cada boot el guardián:
|
||||
1. Verifica que el LXC 102 esté `running` (lo arranca si no).
|
||||
2. Espera a que Docker responda dentro del LXC (hasta 180 s).
|
||||
3. Se asegura de que estén arriba: `coolify-db`, `coolify-redis`,
|
||||
`coolify-realtime`, `coolify`, `coolify-proxy`, `cloudflared` (los inicia si
|
||||
alguno no está).
|
||||
2. Espera a que Docker responda dentro del LXC (**deadline de reloj real**,
|
||||
`COOLIFY_MAX_WAIT`, por defecto 600 s).
|
||||
3. Da un margen de asentamiento (`COOLIFY_SETTLE`, 180 s) para que Docker
|
||||
arranque sus propios contenedores, y solo entonces fuerza el arranque de
|
||||
los que falten: `coolify-db`, `coolify-redis`, `coolify-realtime`,
|
||||
`coolify`, `coolify-proxy`, `cloudflared`.
|
||||
4. Levanta el `cloudflared.service` de systemd dentro del LXC (segundo
|
||||
conector al mismo túnel).
|
||||
5. **Comprueba que el túnel realmente llegó a Cloudflare**: cuenta los
|
||||
`Registered tunnel connection` de este boot y los escribe en el log.
|
||||
|
||||
Sale con código ≠ 0 si algo no se pudo arrancar, para que systemd lo marque
|
||||
`failed` y `Restart=on-failure` reintente (hasta 3 veces por hora).
|
||||
|
||||
Las dos capas son complementarias: `onboot` hace el trabajo normal; el guardián
|
||||
es una red de seguridad que además **auto-repara** (p. ej. un contenedor con
|
||||
`restart=no`) y deja **log** de lo ocurrido tras el apagón.
|
||||
|
||||
### Presupuestos de tiempo (no los bajes a ciegas)
|
||||
|
||||
Medido en el boot del 2026-08-07 16:41: `pve-guests` tarda **78 s** en arrancar
|
||||
el CT 102, el daemon de Docker dentro del LXC solo responde ~**4-5 min** después
|
||||
del encendido, y el último contenedor core (`coolify`) arranca a los **7 m 40 s**.
|
||||
Por eso:
|
||||
|
||||
| Parámetro | Valor | Regla |
|
||||
|---|---|---|
|
||||
| `COOLIFY_MAX_WAIT` | 600 s | espera de Docker, por **reloj real** |
|
||||
| `COOLIFY_SETTLE` | 180 s | margen antes de forzar arranques |
|
||||
| `COOLIFY_PROBE_TIMEOUT` | 20 s | timeout duro de **cada** llamada al LXC |
|
||||
| `TimeoutStartSec` (unit) | 1200 s | **debe superar** `MAX_WAIT + SETTLE` |
|
||||
|
||||
`COOLIFY_LOG` también es sobreescribible, para poder hacer pruebas en seco sin
|
||||
tocar el log de producción.
|
||||
|
||||
Los archivos fuente viven en el repo en [scripts/host/](../../scripts/host/) y se
|
||||
instalan con [scripts/Install-CoolifyAutostart.ps1](../../scripts/Install-CoolifyAutostart.ps1).
|
||||
|
||||
@@ -78,10 +102,17 @@ Estado sano esperado:
|
||||
```
|
||||
onboot: 1
|
||||
startup: order=1,up=30
|
||||
guardian enabled: enabled
|
||||
script executable: yes
|
||||
enabled: enabled
|
||||
state: active
|
||||
result: success
|
||||
timeout: 20min
|
||||
```
|
||||
|
||||
**No basta con `enabled`.** `enabled` solo dice que arrancará; `state`/`result`
|
||||
dicen si la última ejecución funcionó. Una corrida sana del log termina en
|
||||
`=== coolify-autostart done (failures=0) ===`. Si el log se corta justo después
|
||||
de `LXC 102 already running`, el guardián murió esperando a Docker.
|
||||
|
||||
Log del último arranque:
|
||||
|
||||
```powershell
|
||||
@@ -107,6 +138,63 @@ Para validar que el unit está bien formado y en el orden correcto:
|
||||
|
||||
`After` debe incluir `pve-guests.service`; `WantedBy` debe ser `multi-user.target`.
|
||||
|
||||
Para probar la ruta de **fallo** (que el guardián corte y deje `ERROR` en vez de
|
||||
colgarse), apúntalo a un LXC inexistente con un log temporal:
|
||||
|
||||
```powershell
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "env COOLIFY_LXC=999 COOLIFY_LOG=/tmp/ca-test.log COOLIFY_MAX_WAIT=15 COOLIFY_PROBE_TIMEOUT=5 bash /usr/local/bin/coolify-autostart.sh > /dev/null 2>&1; cat /tmp/ca-test.log; rm -f /tmp/ca-test.log"
|
||||
```
|
||||
|
||||
Debe terminar en `ERROR: docker not ready after 15s (wall clock) -> aborting`
|
||||
en ~18 s. No toca producción ni el log real.
|
||||
|
||||
---
|
||||
|
||||
## Incidente 2026-08-07 — el guardián llevaba 2/2 arranques muriendo
|
||||
|
||||
**Síntoma:** `systemctl is-enabled` decía `enabled`, pero la unidad estaba
|
||||
`failed (Result: timeout)` en los dos reinicios reales del día (09:47 y 16:41).
|
||||
El log se cortaba siempre en `LXC 102 already running`, sin línea de `ERROR`.
|
||||
|
||||
**Cronología del boot de las 16:41:**
|
||||
|
||||
| Hora | Evento |
|
||||
|---|---|
|
||||
| 16:41:49 | `pve-guests` arranca el CT 102 |
|
||||
| 16:43:07 | termina `pve-guests` (78 s) y arranca el guardián |
|
||||
| 16:43:08 | `LXC 102 already running` → entra a esperar Docker |
|
||||
| 16:46:05 | Docker empieza a levantar contenedores (`coolify-db`) |
|
||||
| **16:48:07** | **systemd mata al guardián**: `TimeoutStartSec=300` |
|
||||
| 16:48:40 | arranca `coolify` — **33 s después de que el guardián ya estaba muerto** |
|
||||
|
||||
**Causa raíz (tres defectos que se sumaron):**
|
||||
|
||||
1. El bucle de espera contaba **iteraciones de `sleep`, no reloj real**, así que
|
||||
`MAX_WAIT=180` no acotaba nada.
|
||||
2. Las llamadas `pct exec ... docker info` **no tenían timeout** y `docker info`
|
||||
es caro (enumera los ~50 contenedores): con el daemon saturado en el arranque
|
||||
en frío, una sola llamada se bloqueaba minutos y consumía todo el presupuesto
|
||||
en silencio.
|
||||
3. `TimeoutStartSec=300` estaba **por debajo del tiempo real de convergencia**
|
||||
(~7 m 40 s), así que systemd mataba al guardián antes de que pudiera actuar.
|
||||
|
||||
Nunca hubo una ejecución exitosa en un arranque real: la única corrida sana del
|
||||
log (2026-07-08) fue el `-RunNow` manual con todo ya arriba.
|
||||
|
||||
**Por qué no se notó durante un mes:** `-VerifyOnly` solo miraba `is-enabled`.
|
||||
Ahora también reporta `state`, `result`, `timeout` y el journal del último boot.
|
||||
|
||||
**Qué salvó el servicio mientras tanto:** las capas base, que sí funcionaron en
|
||||
los dos reinicios — `onboot=1`, `docker.service` `enabled`, políticas
|
||||
`restart=always`/`unless-stopped` y `cloudflared.service` `enabled` (registró sus
|
||||
4 conectores QUIC a los 3 m 41 s del boot). El guardián es red de seguridad, no
|
||||
el mecanismo principal; por eso el apagón no se notó de cara al usuario.
|
||||
|
||||
**Corrección:** deadline por reloj real, `timeout` duro en cada llamada al LXC,
|
||||
sonda barata `docker version` en vez de `docker info`, margen de asentamiento
|
||||
antes de forzar arranques, verificación de conectores del túnel en el log,
|
||||
`TimeoutStartSec=1200` y `Restart=on-failure`.
|
||||
|
||||
---
|
||||
|
||||
## Rollback
|
||||
@@ -133,10 +221,23 @@ Para validar que el unit está bien formado y en el orden correcto:
|
||||
[cloudflare-tunnel.md](cloudflare-tunnel.md).
|
||||
- `coolify-sentinel` tiene `restart=no` (monitor no crítico); Coolify lo recrea,
|
||||
por eso no está en la lista de contenedores core del guardián.
|
||||
- **El único LXC con `onboot` es el 102.** El LXC `100 hermes` no tiene la marca,
|
||||
así que **no** arranca solo tras un apagón. Es intencional mientras sea
|
||||
secundario; si algún día deja de serlo, `pct set 100 --onboot 1`.
|
||||
|
||||
---
|
||||
|
||||
**Verificado:** 2026-07-08 — instalado y probado en vivo. `onboot=1`,
|
||||
`coolify-autostart.service` `enabled`, guardián ejecutado con éxito (LXC arriba,
|
||||
Docker listo, 6 contenedores core + túnel `running`). `systemd-analyze verify` sin
|
||||
warnings.
|
||||
**Verificado:** 2026-08-07 — auditoría completa tras dos reinicios reales del
|
||||
día. Se detectó y corrigió el fallo del guardián (ver incidente arriba). Estado
|
||||
final: `onboot=1`, unidad `enabled` / `active` / `result=success`,
|
||||
`TimeoutStartUSec=20min`, `Restart=on-failure`, `After` incluye
|
||||
`pve-guests.service`, `systemd-analyze verify` sin warnings. Guardián ejecutado
|
||||
de punta a punta en 9 s con `failures=0`, 6 contenedores core `running`,
|
||||
`cloudflared.service` `active` con **4 conectores registrados**. Ruta de aborto
|
||||
por reloj real probada en seco (corta a los 18 s con `ERROR`). Público
|
||||
verificado a través del túnel: `coolify.urieljareth.org` → 302,
|
||||
`chat.urieljareth.org` → 200.
|
||||
|
||||
**Verificado:** 2026-07-08 — instalación original (`onboot=1` + guardián). La
|
||||
prueba de entonces fue un `-RunNow` manual, no un arranque real; de ahí que el
|
||||
defecto de tiempos no se detectara hasta 2026-08-07.
|
||||
|
||||
Reference in New Issue
Block a user