Skip to content

Alerting Flow — Centralizado via Alertmanager

Last updated: 2026-07-12

El componente central de alertas del homelab es Prometheus Alertmanager (v0.32.1) corriendo en VM 208. Recibe alertas de Prometheus (reglas + Grafana) y las enruta por severity a dos receivers: Telegram (nativo) y Vera (webhook). El viejo flujo basado en n8n queda como legacy (ver más abajo).

🎯 Diseño (actual)

┌────────────────────────┐
│ Prometheus rules        │ ─┐
│ + Grafana alert rules   │  │
└────────────────────────┘  │
                  ┌──────────────────────┐
                  │ Alertmanager v0.32.1 │  (VM 208, prom/alertmanager)
                  │ /home/monxas/appdata/ │
                  │   alertmanager/       │
                  │   alertmanager.yml    │
                  │                       │
                  │ route por severity:   │
                  │  critical|warning ─►vera (continue)
                  │  critical ─► telegram (repeat 1h)
                  │  warning  ─► telegram (repeat 6h)
                  │  inhibit: critical ⊳ warning (equal alertname,instance)
                  └───────┬───────────┬──┘
                          │           │
              ┌───────────▼──┐   ┌────▼──────────────┐
              │ telegram      │   │ vera (webhook)    │
              │ telegram_configs  │ http://192.168.0.245:8099/alert
              │ chat_id       │   │ Bearer auth       │
              │ 730947207     │   │ send_resolved     │
              │ send_resolved │   └───────────────────┘
              └──────┬────────┘
             api.telegram.org
             Bot @Veraclawd_bot
             Chat 730947207

┌────────────────────────┐
│ Proxmox (pmx-50/51)     │ ──► webhook `telegram` (PVE notifications)
│ PVE notifications.cfg   │      → api.telegram.org  (chat 730947207)
└────────────────────────┘

┌────────────────────────┐
│ backup-freshness.sh     │ ──► Telegram vía bot de Vera en CT100
│ (pmx-50, cron 09:00)    │
└────────────────────────┘

⚙️ Alertmanager — configuración

Fichero: /home/monxas/appdata/alertmanager/alertmanager.yml (container alertmanager, imagen prom/alertmanager). Fuente versionada: docs-repo/ansible/roles/observability_collector/files/alertmanager.yml.

  • Route raíz: receiver: telegram, group_by: [alertname, severity], group_wait: 30s, group_interval: 5m, repeat_interval: 12h.
  • Sub-routes:
  • severity=~"critical|warning"vera con continue: true (Vera ve críticas y warnings, pero el flujo sigue evaluando).
  • severity="critical"telegram, repeat_interval: 1h.
  • severity="warning"telegram, repeat_interval: 6h.
  • inhibit_rules: una critical silencia la warning equivalente (equal: [alertname, instance]).

Receiver telegram (nativo)

telegram_configs nativo de Alertmanager (no pasa por n8n): - bot_token_file: /etc/alertmanager/telegram-bot-token - chat_id: 730947207 - parse_mode: HTML, send_resolved: true - Plantilla message con emoji por estado + alertname + severity + lista de alerts (summary/description) + instance.

Receiver vera (webhook)

  • url: http://192.168.0.245:8099/alert
  • send_resolved: true, max_alerts: 0
  • Auth Bearer (credencial en el alertmanager.yml, no versionada en claro).

🎨 Output Telegram

🚨 <b>alertname</b>
Severity: critical
Status: firing

• summary de la alerta
  Instance: host:port

Emoji por estado/severity: 🚨 firing · ✅ resolved. En mensajes de severity manual: 🔴 critical · 🟡 warning · 🟠 high · 🟢 recovery · ℹ️ info.

🔔 PVE → Telegram (nuevo, 2026-07-12)

Proxmox envía todas sus notificaciones a Telegram directamente, sin pasar por Alertmanager. Configurado en /etc/pve/notifications.cfg:

  • Endpoint webhook: telegramPOST https://api.telegram.org/bot{{ secrets.token }}/sendMessage, body con chat_id 730947207, parse_mode Markdown.
  • Enganchado al matcher: default-matcher (mode all) junto a mail-to-root, de modo que cada alerta de Proxmox (incluidos fallos de backup vía mailnotification=failure) llega tanto al mail de root como a Telegram.

🛡️ backup-freshness.sh (nuevo, 2026-07-12)

Monitor de frescura de backups en pmx (/usr/local/sbin/backup-freshness.sh en proxmox-50), cron diario 09:00 (tras las ventanas de backup). Signal-only:

  • Para cada guest con job de backup, busca la última snapshot en PBS (pvesm list pbs).
  • Umbral 48h (THRESH_H): si un guest no tiene backup más reciente que eso, o no tiene ninguno, genera aviso.
  • Críticos (🔴): 100 (Vera), 208 (media), 270/271 (caddy), 280 (rp). El resto son 🟡.
  • Entrega la alerta a Telegram vía el bot de Vera dentro de CT100 (pct exec 100 -- ... source secrets.env ... curl api.telegram.org), sin copiar el token a pmx.
  • Log en /var/log/backup-freshness.log.

🚨 Reglas de alerta activas

Las reglas viven en Prometheus/Grafana y disparan hacia Alertmanager. Grupos:

Reparto de responsabilidades (desde 2026-07-26)

Los dos pipelines tenían 9 reglas duplicadas, así que el mismo evento llegaba dos veces a Telegram con nombres distintos (memory-high y HighMemoryUsage, load-high y HighLoadAverage…). Se deduplicó con un criterio de capacidad, no de preferencia:

Pipeline De qué se ocupa Nº reglas
Prometheus (alerts.yml) Umbrales sobre métricas: host, NAS, SMART/NVMe, backup, servicios 41
Grafana Lo que Prometheus no puede: logs de Loki, probes sintéticos, métricas de Caddy, tendencias 20

Se borraron de Grafana las 9 duplicadas (backup en appdata/grafana/alert-rules-backup-20260726.json). Antes de borrar se comparó expresión a expresión, no sólo el nombre — y ahí apareció la excepción de abajo.

prom-target-down NO es un duplicado de ContainerDown

Se parecen por el nombre y no hacen lo mismo:

  • prom-target-downup{job=~"node|proxmox-nodes|cadvisor"} < 1 — salta si cae un solo target.
  • ContainerDownsum by (job) (up{job=~"cadvisor|node"}) == 0 — salta sólo si caen todos los de un job, y no cubre proxmox-nodes.

Borrar la de Grafana habría dejado ciego el caso "se muere el node_exporter de pmx-51 o del NAS". Se conserva a propósito. Misma lógica al eliminar smart-failed (Grafana, for: 0s): para no perder inmediatez ante un disco muriéndose, nas_smart_failed bajó de 5m a 1m.

Grafana escucha en :3030, no en :3000

En :3000 hay otro contenedor que responde {"success":false,"error":"Authentication not configured"}. Parece un fallo de credenciales de Grafana y no lo es — estás llamando al servicio equivocado.

Para editar reglas: PUT|DELETE /api/v1/provisioning/alert-rules/{uid} con cabecera X-Disable-Provenance: true.

Grafana — homelab-critical (8)

UID Trigger
backup-failed count_over_time({job="vzdump"} \|~ "ERROR:"[10m]) > 0
caddy-upstream-down min(caddy_reverse_proxy_upstreams_healthy) < 1 (2min)
host-silent count_over_time({host=~"proxmox-50\|proxmox2-51\|ubuntu-media-server"}[10m]) < 1
n8n-down-direct n8n DOWN (alerta directa)
pbs-verify-failed PBS verify-job fallido
pihole-down up{job="pihole"} < 1 (3min)
prom-target-down up{job=~"node\|proxmox-nodes\|cadvisor"} < 1 (3min) — cualquier target
tv-gw-down tv-gw LXC DOWN — TV LG sin internet

Grafana — homelab-warning (8)

UID Trigger
caddy-5xx-spike rate(caddy_http_requests_total{code=~"5.."}[5m]) > 0.5 (5min)
caddy-p99-slow p99 latency > 2s (10min)
container-restarting container reinicia >3×/15min
disk-fill-trend disco llenándose en <7d (predictiva)
error-spike rate errores reales >2/s (2min)
loki-grafana-internal-error error interno Loki/Grafana
probe-down probe_success < 1 (3min)
pvesr-fail max(pvesr_fail_count) > 0 (15min) — replicación PVE entre nodos

Grafana — iarq (4)

Stack de iarquitectos en la VM de Carmelo: CPU sostenida y disco de openclaw-vm, errores de iarq y fallos de scraping del RAG. UIDs autogenerados, sin nombre legible.

Prometheus — alerts.yml (41 en 6 grupos)

Reagrupado el 2026-07-26 por dominio real. Antes había un grupo nas-smart de 18 reglas que contenía media_container_missing/_unhealthy (contenedores del stack de media, nada que ver con SMART) y un nas-preventive que separaba BTRFS/mdadm/PCIe del resto de almacenamiento sin criterio.

Grupo Contenido
host_system 7 Disco, memoria, swap, load y ContainerDown de todos los hosts
nas_health 5 NAS vivo, load, memoria, volumen, temperatura
nas_storage 7 Integridad de almacenamiento: RAID, mdadm, BTRFS, PCIe, cache NVMe
nas_smart 15 Sólo salud de disco reportada por SMART/NVMe
backup 2 Ocupación del datastore PBS
services 5 WP-Pulse, Caddy LXC, Remote-Pulse y contenedores de media

🕰️ Legacy — flujo n8n (complementario / en retirada)

Antes de Alertmanager, TODA alerta pasaba por n8n (Beszel Alert Direct Webhook, LXC 200, endpoint POST http://192.168.0.200:5678/webhook/beszel-alert-direct), que clasificaba severity, aplicaba cooldown 5min y reenviaba a Telegram vía la API nativa.

Estado actual: - beszel fue decomisado (LXC 249 retirado), así que su origen de alertas ya no existe. - Alertmanager sustituyó a n8n como sistema central de alertas. - El workflow n8n puede seguir vivo para orígenes puntuales que aún posteen a su webhook (Healthchecks, morning report, watchdog), pero no es el camino canónico. Trátalo como complementario/legacy y no añadas nuevas integraciones ahí.

Detalle del payload/nodos del workflow legacy (por si hay que depurar algo que aún lo use):

  • Format 1 (simple): {source, severity, title, message, url?, skip_cooldown?}.
  • Format 2 (Grafana Alertmanager): n8n auto-detecta alerts: [...].
  • Nodo Process Alert v2: auto-detect Grafana vs simple, clasificación de severity por keyword, cooldown 5min por hash source:severity:title[:40]:message[:60], log en staticData.alertLog (últimas 200).
  • Extraer: pct exec 200 -- n8n export:workflow --id=dKTsixDYpxc76rYI --output=/tmp/wf.json.

🔧 Troubleshooting

"Alerta de Prometheus disparó pero no llegó a Telegram"

Verificar Alertmanager y su config:

# Estado del container
ssh [email protected] 'docker ps | grep alertmanager'
# Alertas activas / silences
curl -s http://192.168.0.208:9093/api/v2/alerts | jq .
# Config cargada
curl -s http://192.168.0.208:9093/api/v2/status | jq .config
# Logs
ssh [email protected] 'docker logs alertmanager --tail 50'

Comprobar que el token de bot existe: /etc/alertmanager/telegram-bot-token dentro del container.

"No llegan alertas de Proxmox a Telegram"

Verificar el endpoint webhook y el matcher en PVE:

ssh [email protected] 'cat /etc/pve/notifications.cfg'
# Probar el endpoint
ssh [email protected] 'pvesh create /cluster/notifications/endpoints/webhook/telegram/test 2>/dev/null || echo "usa la UI: Datacenter -> Notifications -> Test"'

"backup-freshness.sh no avisa / avisa de más"

# Ejecución manual (con umbral bajo para test)
ssh [email protected] 'THRESH_H=1 /usr/local/sbin/backup-freshness.sh'
# Log
ssh [email protected] 'tail -20 /var/log/backup-freshness.log'
Si falla el envío, revisar que CT100 tiene TG_BOT/TG_CHAT en /root/.openclaw/secrets.env.

"Grafana alert disparó pero no llegó"

curl -s -u admin:$GRAFANA_ADMIN_PASS http://192.168.0.208:3030/api/v1/provisioning/contact-points
curl -s -u admin:$GRAFANA_ADMIN_PASS http://192.168.0.208:3030/api/v1/provisioning/policies

📍 Componentes desactivados

  • OpenClaw watchdog timer (openclaw-watchdog.timer) — DISABLED. Causaba spam de alertas durante maintenance.
  • Beszel Alert Forwarder workflow (UID vj0ZOqNN4vkSkzYG) — DISABLED, versión vieja basada en poll a ntfy topic beszel-alerts.
  • Beszel (LXC 249) — decomisado. Ya no emite alertas.