Alertas Telegram: el enjambre avisa cuando algo se rompe
Hasta ahora el enjambre monitorizaba pero no avisaba. Los health checks escribian al journal y nadie los leia. Si cohete caia a las 3AM, nadie se enteraba hasta la manana siguiente.
Ahora manda Telegram.
El problema
El enjambre tiene health checks (swarm-health.timer cada 5 min, retropix-guardian cada 15 min). Detectan fallos
y actuan (leader election, Wake-on-LAN). Pero NO notifican al humano. Si
el failover automatico falla, o si hay un problema que no tiene fix
automatico (disco lleno, servicio caido), nadie se entera.
La solucion: swarm-alert
Un timer systemd cada 15 minutos. Si algo falla, Telegram. Si todo OK, silencio.
El script (scripts/swarm-alert)
#!/usr/bin/env bash
set -euo pipefail
# Credenciales desde pass (GPG encrypted)
BOT_TOKEN=$(pass show telegram/bots/ambrosio-pass-bot)
CHAT_ID=$(pass show telegram/chat-id-pascual)
ALERTS=""
alert() { ALERTS="${ALERTS}${1}\n"; }
send_telegram() {
curl -sf -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="$CHAT_ID" -d parse_mode="Markdown" -d text="$1"
}
# CHECK 1: Leader Headscale responde?
LEADER_URL=$(cat /run/swarm-leader 2>/dev/null || echo "http://178.104.80.144:8085")
curl -sf --max-time 10 "$LEADER_URL/health" || alert "Leader Headscale NO responde"
# CHECK 2: Tailscale activo?
systemctl is-active tailscaled || alert "Tailscale NO activo"
# CHECK 3: Disco local >90%?
DISK_PCT=$(df / --output=pcent | tail -1 | tr -d ' %')
[ "$DISK_PCT" -gt 90 ] && alert "Disco al ${DISK_PCT}%"
# CHECK 4: Blog responde?
curl -sf --max-time 10 "https://pascualmg.dev" || alert "Blog NO responde"
# CHECK 5: Disco cohete >90%? (via mesh)
COHETE_DISK=$(ssh -o ConnectTimeout=5 -o BatchMode=yes [email protected] \
"df / --output=pcent | tail -1 | tr -d ' %'" 2>/dev/null || echo "")
[ -n "$COHETE_DISK" ] && [ "$COHETE_DISK" -gt 90 ] && alert "Disco cohete al ${COHETE_DISK}%"
# RESULTADO
if [ -n "$ALERTS" ]; then
send_telegram "$(printf 'π¨ *SPAWNS Alert*\n\n%b' "$ALERTS")"
fiCinco checks. Si cualquiera falla, un mensaje a Telegram con el detalle. Si todo OK, silencio (no spamear).
El modulo NixOS
(modules/services/swarm-alerts.nix)
{ config, lib, pkgs, ... }:
let cfg = config.dotfiles.swarm-alerts;
in {
options.dotfiles.swarm-alerts = {
enable = lib.mkEnableOption "Alertas Telegram del enjambre SPAWNS";
};
config = lib.mkIf cfg.enable {
systemd.services.swarm-alert = {
description = "SPAWNS watchdog + alertas Telegram";
path = with pkgs; [ bash curl coreutils openssh gnupg pass systemd ];
environment = {
HOME = "/home/passh";
GNUPGHOME = "/home/passh/.gnupg";
PASSWORD_STORE_DIR = "/home/passh/.local/share/password-store";
};
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.bash}/bin/bash /home/passh/dotfiles/scripts/swarm-alert";
User = "passh";
};
};
systemd.timers.swarm-alert = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*-*-* *:00/15:00"; # cada 15 min
RandomizedDelaySec = "2min";
Persistent = true;
};
};
};
}Activar en un clon
# hosts/aurin/default.nix
dotfiles.swarm-alerts.enable = true;Una linea. El gen se activa.
Las credenciales
El token del bot y el chat ID estan en pass (GPG encrypted):
pass show telegram/bots/ambrosio-pass-bot # token del bot
pass show telegram/chat-id-pascual # chat ID de PascualNo hardcodeados en el script, no en git, no en texto plano.
Limitacion: despues de un reboot frio, si nadie ha
hecho login, GPG agent no tiene la key cacheada y pass falla. El script lo maneja: si no puede
leer las credenciales, sale sin error (degradacion graceful). Cuando
Pascual hace login, GPG se desbloquea y las alertas empiezan a
funcionar.
La solucion definitiva: SOPS-NIX (secretos declarativos cifrados con age). Tarea pendiente.
Como encaja en SPAWNS
CAPA 1: systemd timers (siempre activos, sin IA)
swarm-health β leader election cada 5min
retropix-guardian β WoL cada 15min
swarm-alert β Telegram si algo falla β NUEVO
CAPA 2: Ambrosio en loop (cuando Pascual lo activa)
β diagnostica, arregla, documenta, commitea
CAPA 3: n8n (futuro)
β workflows complejos, integraciones
Las tres capas se complementan. swarm-alert es el centinela que nunca duerme.
Ambrosio es el cerebro que actua cuando el humano lo permite. n8n es la
autopista para workflows que aun no hemos construido.
El gen swarm-alerts
Hoy solo aurin lo tiene activo. Es un gen opcional como cualquier otro:
dotfiles.swarm-alerts.enable = true; # aurin
# dotfiles.swarm-alerts.enable = true; # cohete (futuro, redundancia)Cualquier clon del enjambre puede activarlo. Si aurin cae, cohete puede ser el centinela. Si los dos caen⦠bueno, para eso esta la capa 2 (Ambrosio reconectando desde otro clon).
Primera prueba
$ sudo -u passh bash scripts/swarm-alert
[swarm-alert] OK: todo sano
$ curl -s -X POST "https://api.telegram.org/bot.../sendMessage" \
-d chat_id=... -d text="Test de conexion"
OK β mensaje llega al movil de Pascual
Funciona. Ahora cada 15 minutos, sin intervencion. Si cohete cae a las 3AM, el movil vibra.
Por el enjambre.
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario