vmauth con usuario y contraseña delante de VictoriaMetrics y Alertmanager en NetBird (mega-auditoría B-45)
Contexto
scripts/netbird-proxies.sh publica en la VPN NetBird de cada servidor los puertos 8428 (VictoriaMetrics) y 9093 (Alertmanager). Hasta el 25-09-2026 llegaban directos a esos servicios, que no piden usuario ni contraseña: cualquier equipo conectado a la VPN — incluido el runner del CI en OPS — podía borrar series de métricas (/api/v1/admin/tsdb/delete_series) o silenciar alertas sin credencial alguna. La mega-auditoría de septiembre de 2026 lo marcó como hallazgo B-45.
Opciones consideradas
- Restringir por grupo/IP en NetBird: descartada porque el plan Free no da control fino por servicio, y el runner del CI en OPS necesita seguir leyendo métricas (
alertas-ciegas-check.sh), así que cerrar OPS entero no era viable. - Autenticación nativa de cada servicio: descartada porque Alertmanager no trae auth básica de fábrica, y VictoriaMetrics no separa un usuario de solo lectura de uno de escritura sin un proxy delante.
- (elegida) Interponer
vmauth, el proxy oficial de VictoriaMetrics, delante de los dos servicios con dos usuarios: uno de equipo (acceso completo) y uno de solo lectura restringido a/api/v1/query.
Decisión elegida
Dos contenedores vmauth (victoriametrics/vmauth:v1.106.1) en compose.prod.yml, cada uno en su propio puerto de escucha (18428/19093, distinto del de VictoriaMetrics/Alertmanager) para que un proxy NetBird con la IP vieja de un contenedor no pueda saltarse la contraseña por error. scripts/netbird-proxies.sh ahora enruta 8428→vmauth:18428 y 9093→vmauth-am:19093, y cierra el proxy viejo de cada puerto ANTES de buscar el contenedor nuevo: si vmauth no arranca, el puerto queda cerrado, nunca abierto sin contraseña. observability/vmauth/start.sh falla cerrado — si el fichero de contraseña falta, está vacío o no es alfanumérico de ≥24 caracteres, vmauth no arranca. El tráfico interno (web, worker, vmalert) sigue yendo directo a victoriametrics:8428 y alertmanager:9093, sin pasar por vmauth.
Consecuencias
Pros: cierra el acceso de escritura/borrado a cualquier peer de la VPN; el usuario de solo lectura que queda en OPS (el único servidor con un proceso automatizado hablando con estos puertos) no puede borrar series ni silenciar alertas aunque se vea comprometido; fallo cerrado ante contraseña ausente o corrupta.
Contras: las dos sondas de servicios-check en OPS y el cron @reboot de PROD/STAGE tuvieron que cambiar de endpoint (/ → /backend-health, el único que llega al servicio real; vmauth contesta sus propios /health//-/healthy sin más) para no quedar ciegas. Un despliegue hecho antes de crear los ficheros de contraseña deja el contenedor en bucle de reinicio y exige borrar + recrear desde Dokploy (Docker monta una carpeta vacía donde se esperaba un fichero).
Hallazgo adicional (mismo día, commit f90cb92)
Revisando qué otros caminos llegaban a estos puertos aparecieron dos proxies socat supervivientes de la época de Tailscale (tailnet-vm, tailnet-pg, unidades systemd /usr/local/bin/tailnet-proxy-{vm,pg}.sh, Restart=on-failure) que se saltaban vmauth por completo: en STAGE, tailnet-vm se reenganchaba al :8428 apuntando DIRECTO a VictoriaMetrics; en PROD estaba en bucle esperando un puerto que ya no exponía así. Se pararon y deshabilitaron (systemctl disable --now) en los dos servidores — ficheros de unidad conservados, no reactivar. Los sustituye netbird-proxies.sh. Documentado en public/supercontext/AUTOMATISMOS.md.
Status: accepted — desplegado en PROD y STAGE (v1.164.0, PR #614, commit 1f0e1c20). Procedimiento completo para crear/rotar contraseñas, recuperar un arranque sin fichero y volver atrás: context/INFRA.md, sección vmauth.
Véase también
- [[runbook—infra—netbird-proxies]]
- [[decision—20260707—netbird-ssh-apex]]
- [[runbook—infra—hetzner-firewall-solo-netbird]]
- [[concept—general—como-esta-configurado-el-acceso-a-los-servidores-h]]
- [[concept—general—que-es-la-sonda-de-servicios-internos-del-servidor]]
- [[incident—20260924—mega-auditoria-t02-usuarios-privilegios-y-rastro]]