Servicio nuevo en pmpserverubu, en producción desde el 18-19/08/2026.
Cuando una aplicación se cae, GET /api/v1/applications/{uuid}/logs de Coolify devuelve 400 "Application is not running" — justo cuando los logs más falta hacen. Y Docker borra los logs junto con el contenedor, así que el siguiente despliegue destruye la evidencia.
Esto no es hipotético: provocó un incidente real el 12/08/2026. Una aplicación estuvo 53 minutos caída y la causa, escrita en la primera línea del log de arranque, tardó ~50 minutos en identificarse porque nadie podía leer ese log. Ver Capacidad y límites §3.3 y §3.4.
Un servicio systemd, docker-log-archiver.service, escucha el stream de eventos de Docker (docker events) y, en el instante en que un contenedor muere (evento die), captura sus logs y sus metadatos antes de que Docker lo destruya.
| Elemento | Ruta / valor |
|---|---|
| Script | /usr/local/bin/docker-log-archiver.sh |
| Unidad systemd | /etc/systemd/system/docker-log-archiver.service |
| Logs archivados | /data-raid/logs-archive/<app>/<YYYYMMDD-HHMMSS>-exit<codigo>.log |
| Metadatos | mismo directorio, ...meta.json |
| Retención | 30 días |
| Log propio del servicio | /var/log/docker-log-archiver.log |
La unidad lleva Restart=always: el stream de docker events se corta si Docker se reinicia, así que el servicio necesita reiniciarse solo para no perder eventos mientras esté caído.
/data-raid/logs-archive y no en /data-raid/apps/data-raid/apps entra íntegro en el backup diario (ver Servidor §9 — Backups). Los logs archivados son evidencia de diagnóstico con retención propia de 30 días, no datos que haya que respaldar. Meterlos en apps habría inflado el backup sin necesidad — el mismo criterio que ya aplica Capacidad y límites §2 para distinguir datos irreproducibles de datos que no necesitan copia de seguridad.
.meta.json: lo que la API de Coolify no exponeCada entrada incluye:
exit_codeoom_killedfinished_atrestart_countrestart_policyLa API de Coolify no da nada de esto: solo un estado tipo exited:unhealthy sin más detalle (ver Coolify §2.1). Con el .meta.json se distingue en un segundo entre "lo mató el kernel por falta de memoria" y "el proceso terminó con error propio".
Deliberadamente NO incluye el bloque Env del contenedor: contendría los secretos de la aplicación (claves de API, credenciales de base de datos, etc.). El archivador guarda evidencia de diagnóstico, no un volcado completo del contenedor.
| Código | Significado |
|---|---|
0 |
Terminó limpiamente / parada intencionada |
1, 2 |
Error de la aplicación |
137 |
SIGKILL — si oom_killed: true en el .meta.json, lo mató el kernel por memoria |
139 |
SIGSEGV (segmentation fault) |
143 |
SIGTERM — parada ordenada (típico de un redespliegue) |
# Listar los archivos más recientes de una app
ls -lt /data-raid/logs-archive/<app>/ | head
# Ver los metadatos de una caída concreta
cat /data-raid/logs-archive/<app>/<archivo>.meta.json | jq
# Ver el log completo
cat /data-raid/logs-archive/<app>/<archivo>.log
# Estado del propio servicio archivador
sudo systemctl status docker-log-archiver
tail -50 /var/log/docker-log-archiver.log
Este servicio no usa la clave SSH de Coolify ni depende de ella: escucha el socket de Docker directamente en el host. Se documenta cerca de los cambios de seguridad SSH del 19/08/2026 porque ambos forman parte del mismo bloque de trabajo (endurecimiento SSH + mejora de diagnóstico de caídas), no porque compartan mecanismo.