Core2 Watchdog (auto-recovery de contenedores)
Detecta y recupera contenedores Core2 caídos. Diseñado para producción (sd1).
Tambien escucha reinicios de redis-central. Si Chatwoot sigue ejecutando
procesos iniciados antes que Redis, reinicia Rails y Sidekiq para renovar las
conexiones Redis y la suscripcion ActionCable Pub/Sub.
Por qué existe
Incidente mosquitto (jul-ago 2026): tras docker system prune -af + reinicio del
daemon, mosquitto no volvió a arrancar. El watchdog instalado en sd1 tenía un
bug (COMPOSE="docker compose" + "$COMPOSE" → rc=127) y nunca recuperó nada.
Este watchdog corregido detecta por nombre de contenedor (no por compose ps
por proyecto) y recupera con run.sh up.
Cómo detecta
- Para cada proyecto con
run.shbajo el repo root (maxdepth 5), invocabash <run.sh> containers— subcomando añadido aproject_runtime.shque resuelve los nombres esperados usando la MISMA invocación compose del runtime (env files, overrides, modo dev). Esto evita los falsos positivos cuando elPROJECT_NAMEdel run.sh no coincide con la etiqueta real del contenedor (p.ej.mcp_servers/mercadolibre,platform/portal). - Estado por proyecto:
UP— todos los contenedores esperados están corriendo.DOWN— al menos uno no está. → se recupera.SKIP—ENABLED=falseoSKIP_BULK_START=true(p.ej. voxbox). Se ignora.EMPTY/UNKNOWN— sin servicios resolubles (proyectos no-compose). Se ignora.
Cómo recupera
CORE2_COMPOSE_NO_BUILD=true bash <run.sh> up (sin rebuild). El runtime aplica
pre_up hooks, override de imágenes y env files como un up normal.
Uso (local / CLI)
./infra watchdog list # proyectos + estado
./infra watchdog check [proj...] # detecta, no recupera
./infra watchdog run [proj...] # detecta y recupera (self-heal)
./infra test watchdog # test aislado de detección y recuperación
Sin argumentos, run procesa todos los proyectos habilitados. Con argumentos,
filtra por key del proyecto o por nombre de directorio.
Instalación en servidor (sd1)
sudo bash deployment/scripts/health/install-watchdog.sh --root /opt/core2infra
Instala:
/usr/local/sbin/core2-watchdog.sh(script)/usr/local/sbin/core2-redis-chatwoot-watcher.sh(listener de eventos Docker)/etc/systemd/system/core2-watchdog.service(oneshot)/etc/systemd/system/core2-watchdog.timer(cada 2 min,OnBootSec=90s)/etc/systemd/system/core2-redis-chatwoot-watcher.service(listener continuo)- Deshabilita cualquier timer anterior y hace un
checkinicial sin recuperar. - Deja ambos servicios deshabilitados por seguridad. Tras revisar el preflight:
sudo systemctl enable --now core2-watchdog.timer core2-redis-chatwoot-watcher.service
También puede instalarse y habilitarse explícitamente en un paso:
sudo bash deployment/scripts/health/install-watchdog.sh --root /opt/core2infra --enable
Desinstalar:
sudo systemctl disable --now core2-watchdog.timer
sudo systemctl stop core2-watchdog.service
sudo systemctl disable --now core2-redis-chatwoot-watcher.service
sudo rm -f /etc/systemd/system/core2-watchdog.{service,timer}
sudo rm -f /etc/systemd/system/core2-redis-chatwoot-watcher.service
sudo rm -f /usr/local/sbin/core2-{watchdog,redis-chatwoot-watcher}.sh
sudo systemctl daemon-reload
Verificación en producción
# El watchdog detecta y reporta:
sudo CORE2_WATCHDOG_ROOT=/opt/core2infra /usr/local/sbin/core2-watchdog.sh check
# Simular caída y comprobar auto-recovery en la siguiente pasada (≤2 min):
docker stop mosquitto
# ... esperar el timer ...
docker ps | grep mosquitto # debe estar Up
# Caso contenedor BORRADO (el del incidente):
docker rm -f mosquitto
# ... el watchdog lo recrea con `run.sh up` ...
Dependencia Redis -> Chatwoot
core2-redis-chatwoot-watcher.service ejecuta una reconciliacion al arrancar y
despues escucha eventos start de Docker con replay desde el inicio de esa
reconciliacion. Esto cubre reinicios normales, la carrera al suscribirse y
eventos perdidos mientras el listener estaba apagado. Si se reinicia el daemon,
el stream termina y systemd vuelve a conectar el listener automaticamente.
Cuando redis-central arranca:
- Compara su
StartedAtconchatwoot-rails-1ychatwoot-sidekiq-1. - Si Chatwoot es posterior a Redis, no hace nada.
- Si Chatwoot es anterior, espera que Redis este
healthy. - Reinicia solo Rails y Sidekiq y espera que Rails acepte TCP en el puerto 3000.
El listener usa flock, por lo que un evento duplicado no puede iniciar dos
recuperaciones simultaneas. Comandos manuales:
sudo /usr/local/sbin/core2-redis-chatwoot-watcher.sh check
sudo /usr/local/sbin/core2-redis-chatwoot-watcher.sh reconcile
sudo journalctl -u core2-redis-chatwoot-watcher.service -f
Archivos
deployment/scripts/health/core2-watchdog.sh— script standalonedeployment/scripts/health/redis-chatwoot-watcher.sh— dependencia Redis/Chatwootdeployment/scripts/health/install-watchdog.sh— instalador systemddeployment/systemd/core2-watchdog.{service,timer}— unidadesdeployment/systemd/core2-redis-chatwoot-watcher.service— listener de eventosdeployment/scripts/infra/watchdog.sh— comando./infra watchdogdeployment/scripts/utils/project_runtime.sh— subcomandocontainers
Opt-outs (proyectos que no deben arrancarse solos)
Editar project.conf del proyecto:
ENABLED=false # ignora por completo (p.ej. airflow, sites obsoletos)
SKIP_BULK_START=true # no arrancar automáticamente (p.ej. voxbox)
Revisar antes de activar en sd1: processing/airflow y
sites/desarrolloselectronicos no tienen opt-out y actualmente están DOWN; el
watchdog los arrancaría salvo que se marquen.