20-sep: watchdog Gitea (systemd) + fix monitor Kuma

This commit is contained in:
juanminsanz
2026-09-20 12:10:36 +02:00
parent 5d35ec5502
commit 5e8ae0c394
6 changed files with 154 additions and 0 deletions

56
vps/gitea/README.md Normal file
View File

@@ -0,0 +1,56 @@
# Gitea (VPS Contabo) — watchdog + monitor
## Contexto
- `git.v-encore-lab.com` → **185.187.169.109** (VPS Contabo).
- Contenedor `gitea` definido en `/root/docker-compose.yml` (proyecto `root`, red `root_gitea_gitea`).
- Datos en el bind **`/root/gitea/data`** (recrear el contenedor NO los toca).
- Delante: `nginx-proxy-manager` (Gitea escucha en el 3000 interno, sin puerto publicado).
## Incidente 20-sep-2026 (502)
El contenedor `gitea` entró en **bucle de reinicio** (3595 reinicios) por una capa de
escritura corrupta: `/app/gitea/gitea: Permission denied`. La imagen y la DB estaban bien.
Se resolvió recreando el contenedor:
```bash
cd /root && docker compose up -d --force-recreate --no-deps gitea
```
## Watchdog (recrea el contenedor si vuelve a pasar)
`gitea_watchdog.sh` comprueba cada 2 min:
1. Estado del contenedor (`docker inspect`).
2. `docker exec gitea wget -qO- http://127.0.0.1:3000/api/healthz`.
Si falla **2 veces seguidas** (`MAX_FAILS=2`), recrea el contenedor con
`docker compose up -d --force-recreate --no-deps gitea`.
- Log: `/var/log/gitea-watchdog.log` (rota a 1 MB).
- Estado: `/var/lib/gitea-watchdog/fails`.
### Instalación (en el VPS)
```bash
mkdir -p /opt/gitea-watchdog /var/lib/gitea-watchdog
cp gitea_watchdog.sh /opt/gitea-watchdog/ && chmod +x /opt/gitea-watchdog/gitea_watchdog.sh
cp gitea-watchdog.service gitea-watchdog.timer /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now gitea-watchdog.timer
```
Comprobar:
```bash
systemctl list-timers gitea-watchdog.timer
tail -20 /var/log/gitea-watchdog.log
```
## Monitor en Uptime-Kuma
Monitor existente `Gitea - Repositorios` (id 1): `https://git.v-encore-lab.com`, cada 60 s,
notificación **ALERTA MONITORES** (email SMTP). Se corrigió la URL (tenía un punto final:
`https://git.v-encore-lab.com.`).
> Editar el monitor en la DB: parar `uptime-kuma`, `sqlite3 /root/uptime-kuma/kuma.db "UPDATE ..."`,
> y volver a arrancarlo (Uptime-Kuma lee la DB al iniciar).

View File

@@ -0,0 +1,8 @@
[Unit]
Description=Vigilante de Gitea (recrea el contenedor si entra en bucle o deja de responder)
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
ExecStart=/opt/gitea-watchdog/gitea_watchdog.sh

View File

@@ -0,0 +1,10 @@
[Unit]
Description=Ejecuta el vigilante de Gitea cada 2 minutos
[Timer]
OnBootSec=2min
OnUnitActiveSec=2min
AccuracySec=15s
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,60 @@
#!/bin/bash
# Vigilante de Gitea (VPS Contabo).
# Si el contenedor no esta sano N veces seguidas, lo recrea desde /root/docker-compose.yml.
# Los datos viven en el bind /root/gitea/data, por lo que recrear NO los toca.
set -u
DOCKER=/usr/bin/docker
COMPOSE_DIR=/root
CONTAINER=gitea
HEALTH_URL=http://127.0.0.1:3000/api/healthz
LOG=/var/log/gitea-watchdog.log
STATE_DIR=/var/lib/gitea-watchdog
STATE=$STATE_DIR/fails
MAX_FAILS=2
mkdir -p "$STATE_DIR"
touch "$STATE"
log() { echo "$(date '+%F %T') $*" >> "$LOG"; }
# Rotar log si crece demasiado (1 MB)
if [ -f "$LOG" ] && [ "$(stat -c%s "$LOG" 2>/dev/null || echo 0)" -gt 1048576 ]; then
mv -f "$LOG" "$LOG.1"
fi
status=$("$DOCKER" inspect "$CONTAINER" --format '{{.State.Status}}' 2>/dev/null || echo missing)
healthy=0
if [ "$status" = "running" ]; then
body=$("$DOCKER" exec "$CONTAINER" wget -qO- --timeout=8 "$HEALTH_URL" 2>/dev/null || true)
if echo "$body" | grep -q '"status": *"pass"'; then
healthy=1
fi
fi
if [ "$healthy" = "1" ]; then
if [ "$(cat "$STATE" 2>/dev/null || echo 0)" != "0" ]; then
log "Gitea vuelve a estar OK (status=$status)."
fi
echo 0 > "$STATE"
exit 0
fi
fails=$(cat "$STATE" 2>/dev/null || echo 0)
case "$fails" in ''|*[!0-9]*) fails=0 ;; esac
fails=$((fails + 1))
echo "$fails" > "$STATE"
log "Gitea NO saludable (status=$status, fallo $fails/$MAX_FAILS)."
if [ "$fails" -ge "$MAX_FAILS" ]; then
log "Recreando contenedor '$CONTAINER' desde $COMPOSE_DIR ..."
cd "$COMPOSE_DIR" || { log "ERROR: no existe $COMPOSE_DIR"; exit 1; }
if "$DOCKER" compose version >/dev/null 2>&1; then
"$DOCKER" compose up -d --force-recreate --no-deps "$CONTAINER" >> "$LOG" 2>&1
else
docker-compose up -d --force-recreate --no-deps "$CONTAINER" >> "$LOG" 2>&1
fi
log "Recreacion lanzada (exit=$?)."
echo 0 > "$STATE"
fi