Skip to content

Caddy HA failover

Procedimiento para validar manualmente que el VIP 192.168.0.250 migra de caddy-primary (LXC 270, pmx-50) a caddy-secondary (LXC 271, pmx-51) cuando el primario cae. Diseño documentado en ADR-0007 §F4.

Cuándo correr este drill

  • Tras un cambio en keepalived.conf o managed.caddy.
  • Mensualmente como prueba de salud (cron sugerido día 1 de mes).
  • Antes de un reboot planificado del nodo primario.

Pre-flight

# Verificar que el VIP está donde toca (primary)
ssh pmx-50 'pct exec 270 -- ip -4 addr show eth0 | grep 192.168.0.250'
# debe aparecer la IP del VIP .250 además de la propia .40
# Confirmar que ambos Caddy responden por su IP propia
curl --resolve grafana.monxas.casa:443:192.168.0.40 -fsSk https://grafana.monxas.casa/ -o /dev/null && echo OK-primary
curl --resolve grafana.monxas.casa:443:192.168.0.41 -fsSk https://grafana.monxas.casa/ -o /dev/null && echo OK-secondary

Si alguno falla, no continuar con el drill — investigar antes.

Disparar failover

Parar Caddy en el primario. keepalived lleva un vrrp_script check_caddy (/usr/local/bin/check-caddy.sh) con weight -20, así que al fallar el check la prioridad cae y el VIP migra.

ssh pmx-50 'pct exec 270 -- systemctl stop caddy'

Esperar 3-5 segundos (VRRP advertise interval por defecto = 1s; migración suele ser <2s).

Verificación

# El VIP debe estar ahora en el secundario
ssh pmx-51 'pct exec 271 -- ip -4 addr show eth0 | grep 192.168.0.250' && echo "VIP migrado OK"

# Tráfico real funcionando via VIP
curl --resolve grafana.monxas.casa:443:192.168.0.250 -fsSk https://grafana.monxas.casa/ -o /dev/null && echo "Caddy via VIP OK"

Bonus — verificar desde fuera (CF Tunnel apunta al VIP):

curl -fsS https://grafana.monxas.casa/ -o /dev/null && echo "External OK"

Rollback (volver al primary)

Levantar Caddy en LXC 270. Al recuperar el proceso, prioridad sube y VIP regresa:

ssh pmx-50 'pct exec 270 -- systemctl start caddy'
sleep 5
ssh pmx-50 'pct exec 270 -- ip -4 addr show eth0 | grep 192.168.0.250' && echo "VIP back to primary"

Troubleshooting

Síntoma Causa probable Fix
VIP no migra al parar caddy vrrp_script check_caddy roto (/usr/local/bin/check-caddy.sh) o falta weight -20 Revisar /etc/keepalived/keepalived.conf ambos nodos
VIP migra pero Caddy secondary 502 managed.caddy desactualizado en LXC 271 Re-sync: python3 ~/scripts/homelab-ctl.py sync --yes
VIP queda en split-brain (ambos lo anuncian) VRRP packets bloqueados por firewall entre nodos Comprobar conectividad multicast/unicast VRRP entre .40 y .41
Failover OK pero CF Tunnel sigue 502 cloudflared cachea conexión al primario ssh pmx-51 'pct exec 123 -- systemctl restart cloudflared'
Sablier-protected services tarda 30s+ tras failover State Sablier no compartido (esperado, ver ADR §F4) Aceptable; re-wake una vez

Notas

  • No apagar el LXC 270 entero para el drill; basta con parar caddy.service. Apagar el LXC también dispara la migración pero complica el rollback.
  • Frecuencia esperada de failover real: <1/mes. Si pasa más, hay un problema upstream (kernel panic, OOM, red).