DirectAdmin startips — supervisor / auto-restart de IPs virtuales
Fecha: 2026-04-30
- Autor: Abdelkarim Mateos
- Estado: plan de desarrollo, NO IMPLEMENTADO. Reservado para sesión futura.
- Origen: incidente Burcode 2026-04-30 (cloud500 IP virtual
87.98.230.68caída → diagnóstico erróneo y reescritura de 178 A records → reversión). - Informe relacionado:
informes/2026-04/2026-04-30-burcode-cloud500-fail500-dns-glue-muerto.md - Memory:
~/.claude/projects/-Users-abkrim-claude/memory/feedback-da-startips-no-protegido.md
1. Problema
startips.service en DirectAdmin es Type=oneshot:
[Unit]
Description=Start the additional IPs
Wants=network-online.target
After=syslog.target network.target network-online.target
Requires=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/directadmin/scripts/startips
[Install]
WantedBy=multi-user.target
El binario /usr/local/directadmin/scripts/startips recorre /usr/local/directadmin/data/admin/ip.list y aplica IPs adicionales con ip addr add sobre la interfaz primaria. Tras correr, el servicio queda inactive (dead) con code=exited, status=0/SUCCESS. No hay supervisor.
Si las IPs virtuales se caen tras boot por cualquier motivo:
- Reset/restart del subsistema de red (
systemctl restart networkd,netplan apply, mantenimiento del proveedor). - OOM killing de
networkd. - vRack/cloud-init re-aplicando configuración fresca.
- Cambio en
ens3que limpia los aliases.
…las IPs no vuelven hasta el siguiente reboot completo o hasta que alguien lance systemctl start startips.service o bash /usr/local/directadmin/scripts/startips manualmente.
Impacto operativo:
- Dominios DA con virtual host ligado a IP virtual quedan inalcanzables.
- LE auto-renew falla para esos dominios (HTTP-01 challenge no responde).
- Diagnóstico desde fuera puede confundirse con "servidor antiguo desmantelado" (el operador o un agente terminan reescribiendo DNS por error — caso real Burcode 2026-04-30).
El operador reporta que es problema recurrente en su parque DA — segundo frente de trabajo abierto.
2. Diseño propuesto
2.1 Componentes
A) Health-check periódico de IPs virtuales
Script en ~/utilidades/directadmin/check-virtual-ips.sh (versionado en monorepo gitlab.castris.com/root/utilidades):
-
Lee
/usr/local/directadmin/data/admin/ip.list. -
Para cada IP, comprueba si está activa en la interfaz primaria (
ip -4 addr show <iface> | grep <ip>). -
Si UNA IP de la lista NO está en la interfaz, lanza:
systemctl start startips.service(idempotente — el servicio ya existe).- Verifica que tras el restart la IP aparece.
- Si tras el restart sigue sin aparecer, alerta (mail/Telegram) y NO bucla.
B) Systemd timer para el health-check
En /etc/systemd/system/startips-watchdog.{service,timer}:
# startips-watchdog.service
[Unit]
Description=Watchdog for DirectAdmin virtual IPs
After=startips.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/check-virtual-ips.sh
StandardOutput=journal
StandardError=journal
# startips-watchdog.timer
[Unit]
Description=Run virtual IP watchdog every 5 minutes
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
AccuracySec=30s
[Install]
WantedBy=timers.target
Frecuencia 5 min = compromiso entre detección rápida y carga mínima. Ajustable per-server.
C) Alertas
Para no llenar el inbox, política de "alerta solo si auto-fix falla":
- Si auto-restart resuelve → log en journald, sin alerta.
- Si auto-restart falla 2 ciclos consecutivos → mail al operador + Telegram (vía bot existente).
- Métrica opcional: contador en
/var/log/startips-watchdog.metricscon histórico de detecciones.
D) (Opcional) Métricas a Zabbix
Si Castris tiene Zabbix, exponer:
- Item
startips.virtual_ips.expected(entero, lectura deip.list). - Item
startips.virtual_ips.active(entero, IPs activas en interfaz que están enip.list). - Trigger: si
expected != activedurante 2 ciclos → warning.
3. Plan de trabajo (otra sesión)
Fase 1 — POC manual (1-2 horas)
- Escribir
check-virtual-ips.shcon dry-run + apply. - Probar en cloud500 (caso conocido). Forzar caída con
ip addr del 87.98.230.68 dev ens3y verificar detección + auto-fix. - Validar logs en journald.
Fase 2 — Empaquetado (1 hora)
- Mover script a
~/utilidades/directadmin/. - Crear systemd unit + timer.
- Documentar en
~/utilidades/directadmin/README.md. - Empaquetar en script de instalación que copie unit + binarios + habilite el timer.
Fase 3 — Despliegue flota DA Castris (30 min)
-
Auditar qué servidores DA tienen IPs adicionales:
for s in $(sshctx list --panel directadmin --format raw); do n=$(ssh $s 'wc -l < /usr/local/directadmin/data/admin/ip.list') echo "$s: $n IPs" done -
Desplegar el watchdog en los que tienen
>1 IP. -
Servidores conocidos con IPs adicionales: cloud500 (Burcode, 4 IPs). Resto pendiente auditoría.
Fase 4 — Despliegue clientes externos (variable)
Servidores semi-managed (Burcode, otros): pedir autorización antes de instalar.
4. Casos de uso
- Burcode cloud500 (caso semilla del incidente).
- Flota DA Castris que tenga IPs virtuales: srv120, srv121, kvm456, dar, amazzal, titrit, bitatrader (auditar).
- Cualquier DA futuro provisionado con IPs adicionales (regla preventiva: instalar el watchdog en provisión, junto con CSF/DA).
5. Decisiones pendientes (para sesión de implementación)
5.1 Frecuencia del timer
Opciones:
- 5 min: detección rápida, carga insignificante. Recomendado.
- 1 min: detección casi inmediata pero ruido en journald.
- 10-15 min: caída detectable pero ventana de fallo amplia.
5.2 Política de retry
Opciones:
- Auto-restart 1 vez + alerta si falla: simple, evita bucles.
- Backoff exponencial: 1 min → 5 min → 15 min → alerta.
- Solo alerta, sin auto-restart: dejar decisión al operador.
5.3 Alcance del watchdog
Opciones:
- Solo IPs virtuales DA (lo que propone este plan).
- Extender a otros servicios cuya caída sea silenciosa (ej.
dataskqcron,assp, etc.). Probable scope-creep — empezar simple.
5.4 Forma de alerta
Opciones:
- Mail al operador (existing).
- Telegram via bot existente (más rápido).
- Ambos (recomendado para incidentes recurrentes).
6. Riesgos y mitigaciones
| Riesgo | Mitigación |
|---|---|
| El watchdog se mete en bucle restartando startips si éste falla siempre | Implementar contador de retries, parar tras N fallos, alertar |
| Race condition con un cambio legítimo de IP del operador | El watchdog debe leer ip.list cada vez (no cachear); si se cambia ip.list está reflejado |
El propio startips.service es buggy en DA y no funciona en algunos escenarios |
Documentar exit code de startips; si falla repetidamente, alertar para fix manual |
| Ruido en journald | Log conciso (1 línea por chequeo OK, n líneas por incidente) |
7. Anexos
7.1 Script de detección manual (referencia rápida)
#!/bin/bash
# /usr/local/sbin/check-virtual-ips.sh — POC v0
set -euo pipefail
IP_LIST="/usr/local/directadmin/data/admin/ip.list"
IFACE="$(ip -4 route show default | awk '{print $5; exit}')"
MISSING=()
while read -r ip; do
[ -z "$ip" ] && continue
if ! ip -4 addr show "$IFACE" | grep -qE "inet $ip(/| )"; then
MISSING+=("$ip")
fi
done < "$IP_LIST"
if [ "${#MISSING[@]}" -eq 0 ]; then
exit 0 # OK
fi
logger -t startips-watchdog "IPs virtuales caídas: ${MISSING[*]}"
systemctl start startips.service
# verificar tras 2s
sleep 2
STILL_DOWN=()
for ip in "${MISSING[@]}"; do
if ! ip -4 addr show "$IFACE" | grep -qE "inet $ip(/| )"; then
STILL_DOWN+=("$ip")
fi
done
if [ "${#STILL_DOWN[@]}" -eq 0 ]; then
logger -t startips-watchdog "Auto-restart OK, IPs restauradas: ${MISSING[*]}"
exit 0
fi
logger -t startips-watchdog "ALERTA: IPs siguen caídas tras restart: ${STILL_DOWN[*]}"
# TODO: enviar mail/Telegram
exit 1
7.2 Comandos de auditoría de la flota
# ¿Qué servidores DA tienen IPs adicionales?
for s in cloud500 srv120 srv121 kvm456 dar amazzal titrit bitatrader fail500; do
n=$(ssh $s 'wc -l < /usr/local/directadmin/data/admin/ip.list 2>/dev/null')
echo "$s: $n IPs"
done
# ¿Y tras un test de stress, qué dominios usan IPs no-primarias?
ssh <server> '
PRIMARY=$(ip route get 8.8.8.8 | awk "/src/ {print \$NF}")
for f in /usr/local/directadmin/data/users/*/domains/*.conf; do
ip=$(grep "^ip=" "$f" | cut -d= -f2)
if [ "$ip" != "$PRIMARY" ] && [ -n "$ip" ]; then
dom=$(basename "$f" .conf)
echo " $ip → $dom"
fi
done | sort | uniq -c | sort -rn
'
Aviso
Esta documentación y su contenido, no implica que funcione en tu caso o determinados casos. También implica que tienes conocimientos sobre lo que trata, y que en cualquier caso tienes copias de seguridad. El contenido el contenido se entrega, tal y como está, sin que ello implique ningún obligación ni responsabilidad por parte de Castris
Si necesitas soporte profesional puedes contratar con Castris soporte profesional.