No sabría entender este trabajo sin la investigación. Tras tres años en el CERN, al volver a Bilbao decidí trabajar por mi cuenta y seguir investigando y aprendiendo. Creo que emprender es el reto profesional definitivo, y a la vez una expresión de creatividad y un reclamo de libertad.
Zetesis viene del griego ζήτησις, indagación: buscar la causa antes de proponer la solución.
En el post anterior conté qué servidores gestiono y cómo los despliego desde git. Quedó pendiente la red que los une: dos casas, un túnel entre ellas y cuatro servidores en internet. Este post va de eso: los routers, el túnel, las rutas que anuncian los clusters y el acceso entre máquinas con Tailscale.
Como en el anterior, no doy nombres de máquinas, direcciones ni dominios.
Un router VyOS en cada casa
Cada casa tiene un router con VyOS, un sistema operativo para routers basado en Debian que se configura entero con un fichero de texto. Las dos casas lo usan desde junio; antes tenían OPNsense.
Los dos routers hacen lo mismo: cortafuegos por zonas, NAT de salida, DHCP, DNS para la red de casa y su extremo del túnel. El de la casa principal, donde están los dos clusters, además habla BGP con ellos y filtra el DNS. La otra casa guarda las copias de seguridad, y en este post me centro en la principal.
La configuración sale de plantillas en git
La configuración de los routers no se edita en el router. Está en el repositorio de infraestructura, partida en módulos por responsabilidad. El cortafuegos es común a los dos routers y el resto de módulos los tiene cada uno:
Fichero
Qué contiene
10-firewall
La política del cortafuegos por zonas, común a los dos routers
20-interfaces
Las interfaces y el extremo del túnel
30-nat
El NAT de la casa
40-protocols
Las rutas estáticas y BGP
50-service
DHCP, DNS, SSH y monitorización
60-system
Identidad, usuarios y logs
router.env
Los parámetros de la red que no son secretos
secrets.env
Las claves y las contraseñas, cifradas con SOPS
Los módulos de la configuración de un router.
Un script junta los módulos, sustituye los parámetros y escribe un único config.boot por router, que es el fichero que carga VyOS. Si falta un valor o queda alguno sin sustituir, falla antes de escribir nada.
Los secretos de los routers van cifrados con SOPS
Las claves del túnel y las contraseñas de los routers están en git, cifradas con SOPS, una herramienta que cifra los valores de un fichero y deja a la vista los nombres de los campos, y age como algoritmo de cifrado. La clave para descifrarlas está en un gestor de contraseñas, fuera de los clusters.
Son de los pocos secretos que no salen de Infisical. Infisical corre en el cluster de plataforma, y los routers no pueden depender de algo que corre dentro de la red que ellos mismos levantan.
CI comprueba las plantillas y el router se actualiza a mano
Cada cambio en las plantillas pasa por CI, que genera la configuración de los dos routers con secretos de prueba y comprueba su estructura. No valida la sintaxis de VyOS; eso lo hace el router al cargar el fichero.
Aplicar el cambio es manual: genero el config.boot con los secretos reales, lo cargo en el router y lo confirmo con load, commit y save. Después compruebo con compare que no queda ninguna diferencia entre lo que hay en git y lo que corre. Nunca cambio nada en el router en vivo: si hace falta un cambio, va a la plantilla.
Una red para cada cluster, separada de la de casa
En la casa principal, el router separa tres redes: la de casa, con los portátiles, los móviles y la domótica; la del cluster de producción, y la del cluster de plataforma. Los clusters no comparten red con los dispositivos de casa, así que todo el tráfico entre unos y otros pasa por el router, a la ida y a la vuelta.
Los servidores tienen la IP reservada en el DHCP del router, asociada a su MAC, y esas reservas están en las plantillas de git como el resto de la configuración. Si hay que mover un servidor de IP, el cambio se revisa como cualquier otro. Los dos clusters, además, tienen una IP fija en su red.
El DNS de casa filtra anuncios y malware, y sale cifrado
Los dispositivos de casa preguntan el DNS al router. El router guarda las respuestas en caché y pasa el resto a unbound, un resolutor que corre en un contenedor del propio router. Unbound hace tres cosas: bloquea los dominios de listas públicas de publicidad, rastreo, malware y phishing, con mis excepciones en un fichero de git; valida las firmas DNSSEC de las respuestas, y reenvía las consultas a Quad9 cifradas con DNS sobre TLS, así que el operador no ve qué se consulta.
Las listas se descargan y se actualizan solas. Si al arrancar no puede descargar una, unbound resuelve sin filtrar hasta que la consigue, para que el DNS no se caiga por culpa de una lista.
Un túnel WireGuard une las dos casas
Los dos routers están unidos por un túnel de WireGuard, un protocolo de VPN ligero, que está siempre levantado. Las casas no tienen IP fija, así que cada router encuentra al otro por DNS dinámico. Con el túnel, las redes de las dos casas se ven entre sí como si fueran una.
Los clusters anuncian sus servicios por BGP
BGP es el protocolo con el que los routers se cuentan qué redes alcanza cada uno. Los dos clusters están en la casa principal y hablan BGP con su router, cada uno con su propio número de sistema autónomo. Cada cluster reserva la mitad alta de su red para servicios que necesitan una IP propia, accesible desde la red de casa. Cuando creo uno de tipo LoadBalancer con una etiqueta concreta, Cilium, la capa de red de los clusters, le da una IP de ese rango y se la anuncia al router, que la aprende como una ruta suelta. No tengo que tocar el router por cada servicio nuevo: el cluster lo anuncia y el router aprende la ruta.
Así, cualquier dispositivo de la red de casa puede hablar con un servicio de los clusters, si el cortafuegos del router y Cilium lo permiten. Los clusters también se hablan entre ellos por esas rutas: el de producción envía sus métricas y sus logs al de plataforma.
Tailscale: cada máquina con su identidad
Para todo lo demás uso Tailscale, una red privada entre máquinas montada sobre WireGuard. Cada máquina entra en ella con su propia identidad y una etiqueta, y las conexiones entre máquinas van cifradas, estén en casa o en internet. Quién puede hablar con quién lo decide una política: cada acceso dice quién, a dónde y por qué puerto. Lo que no está en la política no pasa.
Quién
A dónde
Puerto
Servidor de entrada
Cluster de producción
80 y 443
VPS y clusters
Almacenamiento de las copias
Uno solo
Administrador
Todas las máquinas
Todos
Algunos accesos de la política, sin nombres.
El resto de accesos sigue el mismo patrón: un origen, un destino y solo el puerto que hace falta. A las máquinas que no tienen Tailscale, como las de la red de casa, se llega por routers de subred, que anuncian esa red dentro de Tailscale.
La política también está en git
La política de Tailscale es un fichero del mismo repositorio, con sus tests: casos que dicen qué conexiones se tienen que aceptar y cuáles se tienen que rechazar. Al fusionar un cambio en main, un workflow ejecuta los tests y, si pasan, aplica la política. Las rutas que anuncian los routers de subred también se aprueban desde ese fichero, no a mano en el panel.
El workflow solo corre al fusionar en main y no en los pull requests. Necesita la credencial de Tailscale, y en un pull request cualquier rama que tocara el fichero podría usarla.
Lo público llega por el servidor de entrada
Las webs públicas no entran directamente en las casas. El DNS está en Cloudflare, pero sin su proxy: los registros apuntan al servidor de entrada, un VPS con Caddy, un servidor web, y CrowdSec. Caddy recibe la petición, CrowdSec bloquea las direcciones con mala reputación, y la petición sigue por Tailscale hasta Traefik, la entrada del cluster, que la pasa al servicio.
Cómo esquivo los bloqueos de LaLiga
LaLiga tiene una autorización judicial, vigente hasta el final de la temporada 2026/27, para que Movistar, MasOrange, Vodafone y DIGI bloqueen durante los partidos las IPs de Cloudflare que asocia a retransmisiones piratas. Bloquean la IP entera, y esas IPs las comparten miles de webs. Con la web pirata caen todas las demás, sin aviso.
Me di cuenta el día que empezó la liga, en agosto: dos de mis webs no abrían desde el móvil, y las que servía directamente desde el VPS funcionaban. Encontrar la causa me costó horas, porque desde la fibra de casa, con un operador que no aplicaba el bloqueo, todo respondía bien.
El bloqueo se aplica en la red del operador de quien visita la web, no en el centro de datos: desde el VPS, Cloudflare responde sin problema. Así que el servidor de entrada da la cara y Cloudflare se queda detrás. Las webs estáticas se siguen publicando en Cloudflare Pages, y Caddy les reenvía las peticiones: el despliegue no cambia y la IP bloqueable solo la ve el VPS.
Para eso, el DNS apunta al VPS con un registro A sin proxy. Un CNAME con proxy resolvería a las IPs de Cloudflare aunque el destino fuera Pages. El certificado HTTPS lo saca Caddy de Let's Encrypt con un desafío DNS, que funciona sin el proxy, y sirve también de comprobación: si la web enseña el certificado de Let's Encrypt y no el que pone Cloudflare, el tráfico ya no pasa por su proxy.
Cuando la web corre en una máquina mía con IP propia, como uno de los foros de clientes, el Caddy va en esa misma máquina y el registro apunta a ella: pasar por el servidor de entrada solo añadiría un salto. La regla es la misma, que la cara la dé un Caddy mío con el registro sin proxy. La excepción es lo que está detrás de Cloudflare Access, porque ahí el proxy es el que pide el login, y asumo que puede no abrir durante un partido.
Publicar una web nueva es añadir su bloque al fichero de Caddy del repositorio, que el agente del servidor aplica al fusionar, crear el registro DNS sin proxy y darla de alta en las sondas. Las sondas comprueban cada dominio y avisan por Telegram si uno lleva tres minutos caído. Salen desde casa, así que detectan las caídas del servicio pero no el bloqueo de otro operador; para eso miro hayahora.futbol.
La red también se revisa en git
Los routers, con sus reservas de IP y su DNS, la política de Tailscale y los servicios que anuncian los clusters están en el mismo repositorio que el resto de la infraestructura. Un cambio en la red es un commit que se puede revisar antes y consultar después. Más detalle de cada pieza, con los nombres de las máquinas, en Montar un homelab desde cero: las redes.