Resumen
Alertmanager es el componente que recibe alertas de vmalert, las agrupa (para evitar spam), aplica delays anti-falso-positivo, y envía notificaciones al equipo infra vía email (Resend SMTP).
El destinatario es logcrearack@esfericlabs.com (buzón canónico para alertas de runtime SaaS) y el remitente es CreaRack Pro <noreply@crearack.com> (dominio verificado en Resend). Desde el 28-07-2026 el asunto etiqueta el entorno de origen ([CreaRack PROD] / [CreaRack STAGE] / [CreaRack LOCAL]) — antes iba hardcodeado a PROD.
Despliegue
Imagen
prom/alertmanager:v0.27.0
Configuración en compose
Local (compose.observability.yml)
alertmanager:
image: prom/alertmanager:v0.27.0
container_name: crearack_alertmanager
volumes:
- ./observability/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- ./observability/alertmanager/smtp_password:/etc/alertmanager/smtp_password:ro
- alertmanager_data:/alertmanager
command:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--storage.path=/alertmanager"
ports:
- "9093:9093"
restart: unless-stopped
networks:
- crearack_internal
PROD/STAGE (compose.prod.yml — ambos Dokploy usan este archivo)
alertmanager:
image: prom/alertmanager:v0.27.0
restart: unless-stopped
volumes:
- ./observability/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- ../files/smtp_password:/etc/alertmanager/smtp_password:ro
- alertmanager_data_prod:/alertmanager
command:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--storage.path=/alertmanager"
- "--web.external-url=${ALERTMANAGER_EXTERNAL_URL:-http://crearack-prod.netbird.cloud:9093}"
networks:
- crearack_internal
Nota importante: En PROD, la ruta de smtp_password es ../files/ (sibling del repo clonado en code/), no en el repo mismo. Esto es porque Dokploy no clona archivos gitignored — el secret se proporciona separadamente en cada Dokploy (STAGE y PROD).
Rutas y volúmenes
- Configuración:
./observability/alertmanager/alertmanager.yml→/etc/alertmanager/alertmanager.yml. - Secret (API key Resend):
./observability/alertmanager/smtp_password(local) o../files/smtp_password(PROD/STAGE). - Storage: volumen
alertmanager_dataoalertmanager_data_prod(persistencia de estado). - API web: puerto
9093— en los servidores se expone SOLO a la VPN NetBird vía proxy socat (scripts/netbird-proxies.sh, relanzar tras cada recreate). El botón “View in Alertmanager” del email usaALERTMANAGER_EXTERNAL_URL(Dokploy STAGE la define ahttp://crearack-staging.netbird.cloud:9093; PROD usa el default).
Configuración
alertmanager.yml
Archivo en observability/alertmanager/alertmanager.yml. Estructura:
global:
resolve_timeout: 5m
smtp_smarthost: "smtp.resend.com:587"
smtp_from: "CreaRack Pro <noreply@crearack.com>"
smtp_hello: "crearack.com"
smtp_auth_username: "resend"
smtp_auth_password_file: "/etc/alertmanager/smtp_password"
smtp_require_tls: true
route:
receiver: "logcrearack-email"
group_by: ["alertname"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: "logcrearack-email"
email_configs:
- to: "logcrearack@esfericlabs.com"
send_resolved: true
headers:
Subject: '[CreaRack {{ or .CommonLabels.env "prod" | toUpper }}] {{ .Status | toUpper }} · {{ .CommonLabels.alertname }}'
Etiqueta de entorno env (28-07-2026 · PR #348)
El asunto lee la label env que vmalert estampa en cada alerta con --external.label=env=${ALERT_ENV:-prod} (compose.prod.yml):
- PROD: sin
ALERT_ENVen su Dokploy → defaultprod. - STAGE:
ALERT_ENV=stageen el env del Dokploy de STAGE. - Local:
--external.label=env=localfijo en compose.observability.yml. - Fallback:
or .CommonLabels.env "prod"cubre alertas de un vmalert anterior a la label.
⚠️ Footgun (s95): un cambio en alertmanager.yml NO se aplica con el deploy — el bind del archivo queda apuntando al inode viejo tras el git pull. Hay que docker compose -p <project> -f compose.prod.yml up -d --force-recreate --no-deps alertmanager (y relanzar netbird-proxies.sh, la IP cambia).
Parámetros clave
| Parámetro | Valor | Propósito |
|---|---|---|
resolve_timeout | 5m | Si una alerta no se confirma en 5m, se marca resuelta. |
smtp_smarthost | smtp.resend.com:587 | Servidor Resend con STARTTLS. |
smtp_auth_username | resend | Usuario PLAIN para Resend SMTP. |
smtp_auth_password_file | /etc/alertmanager/smtp_password | Ruta al secret (API key). |
smtp_require_tls | true | Obliga TLS. |
group_by | ["alertname"] | Agrupa por nombre de alerta (evita duplicados si múltiples targets activan la misma). |
group_wait | 30s | Espera 30s antes de enviar email (permite agregar más alertas). |
group_interval | 5m | Recomputa grupos cada 5m. |
repeat_interval | 4h | Si una alerta sigue activa, reenvía cada 4h (evita spam). |
send_resolved | true | Envía notificación también cuando la alerta se resuelve. |
Secret: API key de Resend
Cada entorno usa su PROPIA clave send-only (revocación granular, directiva s69):
- PROD: clave original del Hito A (s94), verificada viva 28-07-2026.
- STAGE: clave dedicada
alertmanager-stagecreada el 28-07-2026 — la clave que STAGE tenía montada estaba revocada y el535 Authentication credentials invalidsolo afloró en el primer simulacro de la task #133 (STAGE no había disparado ninguna alerta en 2 meses). Lección: una clave montada ≠ una clave viva; el simulacro E2E es la única verificación real del canal.
Dónde obtener
- Login en Resend (https://resend.com).
- Crear una API key con permiso Sending access only, una por entorno.
- Copiar la clave (formato:
re_...).
Almacenamiento
-
Local: copiar a
observability/alertmanager/smtp_password(es gitignored).echo "re_..." > observability/alertmanager/smtp_password chmod 600 observability/alertmanager/smtp_password -
PROD/STAGE: escribir
files/smtp_passworden el host de Dokploy (NO en el repo),chmod 644(el contenedor corre comonobody; 600 de root da permission denied — footgun s95). Tras cambiar la clave:docker restartdel alertmanager (el password_file se relee, pero el restart garantiza estado limpio).
Verificación
- El dominio
crearack.comdebe estar verificado en Resend (se hizo en s94). - Validar una clave sin enviar nada:
curl -s -H "Authorization: Bearer $KEY" https://api.resend.com/emails→"restricted to only send emails"= clave VIVA send-only ·"API key is invalid"= clave muerta. (Así se diagnosticó la de STAGE el 28-07.)
Comportamiento
Ciclo de notificación
- vmalert envía una alerta:
{alertname: "CreaRackDown", severity: "critical", env: "stage", ...}. - Alertmanager recibe en
POST /api/v1/alerts. - Agrupa: busca alertas activas del mismo nombre (
alertname). - Espera 30s (
group_wait): agrupa más si llegan. - Envía email:
- Asunto:
[CreaRack STAGE] FIRING · CreaRackDown(el entorno sale de la labelenv). - Body: plantilla de Alertmanager con detalles.
- De:
CreaRack Pro <noreply@crearack.com>. - A:
logcrearack@esfericlabs.com.
- Asunto:
- Si sigue activa 4h después, reenvía.
- Cuando se resuelve (
firing=false), envía otra notificación:[CreaRack STAGE] RESOLVED · CreaRackDown.
Métricas E2E medidas (simulacros 28-07-2026, STAGE)
Web parada → alerta activa en Alertmanager: ~2m15s (scrape + for: 1m + eval 30s). Email FIRING: +30-60s más. El disparo real de PROD del 29-06-2026 cuadró: firing 11:51 → email entregado 11:57.
UI web
En http://crearack-prod.netbird.cloud:9093 (PROD) · http://crearack-staging.netbird.cloud:9093 (STAGE) — solo VPN NetBird:
- Alertas activas.
- Grupos agregados.
- Silenciadores.
- Historial.
Debugging
# Ver logs (los envíos EXITOSOS no se loguean a nivel info; los fallos sí, como warn/error con retry)
docker logs <alertmanager> -f
# Chequear configuración
docker exec <alertmanager> cat /etc/alertmanager/alertmanager.yml
# Alertas activas (amtool viene en la imagen)
docker exec <alertmanager> amtool alert query --alertmanager.url=http://localhost:9093
Errores comunes
535 5.7.8 Authentication credentials invalid
- Causa: API key de Resend inválida o revocada (caso STAGE 28-07: montada pero muerta).
- Solución: validar la clave contra
api.resend.com/emails(ver §Verificación); si está muerta, crear una nueva send-only y reescribirfiles/smtp_password+ restart.
starttls: certificate verify failed
- Causa: certificado SSL de
smtp.resend.comno es confiable (raro). - Solución: actualizar CA bundles del contenedor.
Email no llega
- Causa: dominio
crearack.comno verificado en Resend, o clave muerta fallando en silencio (solo se ve en los logs como warn de retry). - Solución: verificar dominio en Resend dashboard + grep de
error|fail|warnen los logs del alertmanager.
smtp_password: No such file or directory / Is a directory
- Causa: fichero no existe (docker crea un DIRECTORIO vacío al montar el bind) o ruta errónea.
- Solución:
rm -rfel directorio fantasma y crear el archivo con la clave (644).
Integraciones futuras
- Webhook: añadir receiver type
webhook_configspara enviar a Slack/Discord además de email. - Templating avanzado: customizar asunto/body por tipo de alerta.
Véase también
- [[feature—observability—alerting-prod-s95]]
- [[decision—20260529—plan-hardening-post-master-hito-a]]
- [[entity—observability—service—vmalert]]
- [[entity—observability—service—victoria-metrics]]
- [[runbook—observability—alerting-setup]]
Referenciado desde
- Decisión: Plan Hardening post-Máster — Hito A (Alerting de PROD)
- Entidad: vmalert — evaluador de reglas de alerta en tiempo real
- Falsas alarmas HighErrorRate por el 501 deliberado de SpinetiX WebDAV
- Feature: Alerting de PROD — avisos cuando algo va mal por dentro
- Feature: Avisos del requisito 24/7 del Sentinel
- Runbook: Setup de Alerting en Dokploy (STAGE y PROD)
- Sistema de alarmas de PROD (vmalert + Alertmanager)