Simplifica tu homelab: adiós IPs y puertos, hola .internal hostnames
TL;DR — Lo que vas a tener al final
- Tiempo de setup: 4-6 horas para setup completo.
- Requisitos: CPU con VT-x, 16+ GB RAM, 64+ GB SSD.
- Resultado: Homelab con VMs/LXC, backups PBS, monitoring integrado.
- Troubleshooting: Logs de Proxmox, snapshots, restore drills mensuales.
Por qué tu homelab necesita nombres limpios
Si llevás más de un mes con servicios self-hosted ya sabes lo que pasa: jellyfin.internal queda perfecto en una libreta, pero tu realidad es 192.168.0.42:8097. Y esa realidad se rompe sola: cambiás un cable, el DHCP te asigna otro IP, todos los bookmarks quedan apuntando a un fantasma, y el remoto de la tele deja de abrir Netflix porque tiene que tipear la dirección completa con un teclado de 12 botones.
El artículo de Abhishek Prakash en It’s FOSS (1-oct-2026) ataca exactamente ese punto: dejar de recordar IPs y puertos y pasar a nombres como jellyfin.internal. La solución que él muestra se monta en dos piezas que ya existen en cualquier homelab Linux maduro: AdGuard Home como servidor DNS de toda la LAN y como navegador, y Nginx Proxy Manager como reverse proxy que mapea nombre + puerto hacia el servicio correcto. En este post lo vas a montar desde cero, paso a paso, con los tropiezos reales que vas a encontrar (incluyendo los que el autor original se comió).
Por qué .internal y no .local ni .lan
Antes de instalar nada, el TLD. Las opciones que circulan en foros tienen problemas concretos:
.local: reservado para mDNS (Bonjour, Avahi). Si tu servidor sirve a un device que ya habla Bonjour, lo resuelve antes de preguntarle a tu AdGuard y te queda comportamiento inconsistente..lany.home: no están reservados hoy, pero pueden venderse mañana. Pasa con.devcuando Google lo compró y dejó de ser gratuito..home.arpa: el oficial RFC 8375, pero es feo de tipear y la mayoría de los browsers lo subrayan raro.
En julio de 2024, ICANN reservó .internal permanentemente para uso privado en el DNS raíz, según las resoluciones especiales del 29 de julio. La IANA confirmó la decisión. Esto significa que .internal nunca será un TLD comercial: es la opción correcta para homelabs.
Verificable en la propuesta pública de ICANN y en el blog de IANA. Una vez que esté reservado, no hay riesgo de colisión con un dominio real.
El plano: dos cajas hacen todo el trabajo
El setup mínimo tiene dos componentes:
- Servidor DNS de red: AdGuard Home corriendo 24/7 en una caja de bajo consumo (Raspberry Pi 4/5, NUC viejo, mini PC de 10W). Recibe todas las consultas DNS de la LAN, bloquea trackers, y resuelve tus nombres
.internalcontra IPs fijas. - Reverse proxy: Nginx Proxy Manager (NPM) en la misma caja o en una segunda. Recibe el tráfico HTTP/HTTPS entrante, lee el header
Host, y lo redirige al IP:puerto del servicio real.
Dado que el DNS solo resuelve nombres a IPs (no a puertos), necesitas el proxy para esconder el puerto. Por eso las dos cajas tienen que estar siempre arriba: si AdGuard se cae, todo tu tráfico sale por el fallback del router y los .internal no resuelven más.
El esquema de direccionamiento que recomiendo es el siguiente:
| Dispositivo | IP | Notas |
|---|---|---|
| Router / gateway | 192.168.0.1 | DHCP y NAT |
| Caja DNS + proxy | 192.168.0.4 | 24/7, AdGuard + NPM |
| Cajas secundarias | 192.168.0.5-9 | Servicios pesados (AI local, NAS) |
| Pool DHCP dinámico | 192.168.0.10-253 | Teléfonos, laptops, IoT |
La regla de oro: deja el inicio del pool DHCP en .10, no en .2 como viene por defecto. Eso te da los primeros 8 octetos para asignar IPs fijas a tus servidores sin tocar reservas.
Paso 1: IPs fijas vía DHCP reservations
Todo el setup depende de que las IPs de tus servidores NUNCA cambien. Si el DNS server cambia de IP, todo se rompe. Por eso: DHCP reservation, no IP estática en el device.
En la mayoría de routers (TP-Link, MikroTik, OPNsense, UniFi lo que tienen esta opción bajo DHCP server / Address reservation / Static mappings). En Linux, sacás la MAC con:
ip link show eth0
# link/ether aa:bb:cc:dd:ee:ff
Y la MAC también corre, lo confirmas con un ARP table lookup:
ip neigh show
# 192.168.0.5 dev eth0 lladdr aa:bb:cc:dd:ee:ff REACHABLE
El lugar más fácil sigue siendo el router: ve todos los devices conectados y los puedes resolver desde ahí mismo. La MAC del device la terminás pegando en el campo MAC de la reserva DHCP.
Para que el cambio tome efecto, el device tiene que renovar su lease DHCP. La mayoría lo hace automáticamente cada 24h, pero si tienes urgencia a través de una reconexión:
sudo dhclient -r eth0 && sudo dhclient eth0
Y verifica que ya tiene la renovada IP:
ip addr show eth0 | grep inet
Paso 2: AdGuard Home en la caja 24/7
AdGuard Home es el servidor DNS de la LAN. Hace dos cosas por nosotros: una falla de bloqueo de ads/trackers a nivel DNS (similar a Pi-hole pero con mejor UI y soporte nativo de DoH/DoT), y dos falla de resolver tus .internal a IPs fijas.
Instalación estándar en Debian/Ubuntu:
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install_deps.sh | bash -x &
curl -s -S -L -o /tmp/agh.tar.gz https://github.com/AdguardTeam/AdGuardHome/releases/latest/download/AdGuardHome_linux_amd64.tar.gz &
sudo tar -C /opt -xzf /tmp/agh.tar.gz &
sudo /opt/AdGuardHome/AdGuardHome -s install
El binario interactivo te pregunta dos cosas: puerto de admin UI (default 3000) y puerto DNS (default 53). Si el 53 está ocupado, lo descubrís así:
sudo ss -tulpn | grep :53
El -p te muestra el proceso. Si tienes un Pi-hole corriendo o un systemd-resolved con stub listener en el 5353, lo desactivás antes:
sudo systemctl disable --now systemd-resolved
sudo sed -i 's/^#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf
sudo systemctl restart systemd-resolved
El setup inicial corre en http://localhost:3000 (o el IP fijo que pusi antes .4). El wizard te genera el archivo AdGuardHome.yaml en /opt/AdGuardHome/ y arranca el servicio.
Paso 3: que la red use AdGuard como servidor
AdGuard está corriendo, pero ningún device lo está consultando. tienes dos lugares donde configurar el DNS server que entrega el router:
H4: a nivel router (recomendado)
Vas a la configuración DHCP del router y cambiás el DNS primario a la IP de AdGuard (192.168.0.4). DNS secundario a 1.1.1.1 (Cloudflare) como fallback si AdGuard se cae.
El truco de esta configuración es que el router, en lugar de ser el DNS server, se vuelve un proxy: los devices le preguntan al router, y el router le pregunta a AdGuard. Por eso el query log de AdGuard muestra al router como la fuente de casi todas las consultas, no a los devices individuales.
H4: a nivel device
Si quieres per-device stats y logging, configuras el DNS directamente en cada device. En GNOME, lo cambiás vía NetworkManager:
nmcli connection modify "Home-WiFi" ipv4.dns "192.168.0.4"
nmcli connection modify "Home-WiFi" ipv4.ignore-auto-dns yes
nmcli connection down "Home-WiFi" && nmcli connection up "Home-WiFi"
verificas con:
resolvectl status
# DNS Servers: 192.168.0.4
Si después de cambiar el DNS el tráfico del browser no aparece en el log de AdGuard, el cambio no se aplicó a la conexión activa. Reconectá el Wi-Fi.
H4: el gotcha del DNS secundario
El 1.1.1.1 como secundario es la red de seguridad: si AdGuard se cae, internet no se va a negro. Pero viene con un costo. Los clients DNS no siempre esperan al primario antes de probar el secundario, y cuando el resultado llega de Cloudflare, los ads pasan y los .internal no resuelven. Si ves un nombre que falla ocasionalmente, este es el culpable.
Paso 4: crear los nombres .internal
Una vez que AdGuard es el DNS server de la red, creas los nombres. Vas a Filters → DNS rewrites → Add DNS rewrite, ponés el dominio (ej: jellyfin.internal) y la IP destino.
El detalle crítico: DNS rewrite solo acepta IPs, no puertos. Si tienes dos servicios en la misma caja (zimaboard.internal con Jellyfin en :8097 y Home Assistant en :8123), los dos apuntan a la misma IP 192.168.0.4. Acá es donde necesitas Nginx Proxy Manager para mapear el nombre al puerto correcto.
Paso 5: Nginx Proxy Manager para esconder puertos
DNS solo traduce nombre a IP en lugar de puerto. Para que http://jellyfin.internal funcione sin escribir :8097, algo tiene que escuchar en el puerto 80, leer qué host pidió el cliente, y arrancar el tráfico al puerto correcto. Ese algo es un reverse proxy.
Instalación vía Docker Compose (lo más limpio):
mkdir -p /opt/npm/data /opt/npm/letsencrypt
cat > /opt/npm/docker-compose.yml <<YAML
services:
app:
image: jc21/nginx-proxy-manager:latest
ports:
- '80:80'
- '443:443'
- '81:81'
image: jc21/nginx-proxy-manager:2.12.6
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
restart: unless-stopped
YAML
cd /opt/npm && docker compose up -d
El admin UI queda en http://192.168.0.4:81. El default login es [email protected] / changeme, te obliga a cambiarlo en el primer login.
H3: agregando un proxy host
Para cada servicio, vas a Hosts → Proxy Hosts → Add Proxy Host:
- Domain Names: el hostname, ej:
jellyfin.internal - Scheme:
http(ohttpssi el service tiene TLS) - Forward Hostname / IP: el IP del device que corre el servicio
- Forward Port: el puerto real del servicio, ej:
8097 - Websockets Support: ON (Jellyfin, Home Assistant y la mayoría lo necesitan para mantener el socket vivo)
El label “Public” en NPM es engañoso: solo significa que NPM no le pone su propio login. Los nombres .internal solo resuelven por tu AdGuard, así que nadie de afuera los alcanza. Para acceso externo, la herramienta correcta es Tailscale (no abrir puertos en el router).
Troubleshooting: los tres problemas que vas a tener
El setup nunca sale 100% limpio. Estos son los tres problemas más comunes y cómo resolverlos.
H3: Home Assistant tira 400: Bad Request
Home Assistant rechaza requests que vienen proxificados a menos que confíe explícitamente en el proxy, como protección contra spoofed headers. El fix va en configuration.yaml:
http:
use_x_forwarded_for: true
trusted_proxies:
- 172.17.0.0/16 # subnet completa del bridge de Docker
Confiar en la subnet completa en lugar de un IP solo es más durable: si recreás el container de NPM, su IP cambia. reinicias Home Assistant:
sudo docker restart homeassistant
H3: Netflix deja de funcionar en la TV
AdGuard bloquea por default varios telemetry endpoints. Netflix hace un connectivity check contra logs.netflix.com y si no lo alcanza, asume que no hay internet y se niega a abrir. Permitís esos dominios en AdGuard → Filters → Custom filtering rules:
@@||logs.netflix.com^
@@||nrdp26.logs.netflix.com^
Reinicializás el app de Netflix en la TV y vuelve a funcionar. Si rompés algo más después de activar AdGuard, el query log es el primer lugar para mirar.
H3: conflictos de puerto
El puerto 80 colisiona con algo (Apache, nginx anterior, el dashboard del router, etc.). Lo descubrís así:
sudo ss -tulpn | grep :80
Si dice docker-proxy, buscás a qué container pertenece:
sudo docker ps --format "{{.Names}}: {{.Ports}}"
La decisión es entre remover el container conflictivo o mover el otro servicio a otro puerto. Lo que NO tienes que hacer es cambiar el puerto de NPM: si NPM ya no escucha en :80, el reverse proxy no sirve para nada y vuelves a tipear puertos.
Agregar un nuevo servicio después
Una vez que el setup está estable, agregar un nuevo servicio son dos pasos:
- DNS rewrite en AdGuard: nombre → IP del device
- Proxy host en NPM: nombre → IP:puerto del servicio, con WebSockets ON
Tiempo total: dos minutos. Sin tocar nada del router, sin DHCP reservations nuevas (el IP fijo ya existe). El resto es edit-free.
Cuándo NO vale la pena este setup
Si tienes un solo servicio self-hosted (ej: solo Plex) y un IP fijo, no necesitas todo esto. Con un bookmark en el browser o un alias SSH alcanzás.
Si administras la red desde OPNsense o desde un firewall pfSense que ya tiene DNS resolver + reverse proxy integrado (HAProxy, Caddy, nginx nativo), todo este setup es redundante. Ponés las reglas en el firewall y listo.
Si tu homelad es de 20+ devices con muchos servicios y quieres algo que escale sin tener que tocar configs a mano, este setup es para ti.
Resumen
Pasar de 192.168.0.42:8097 a jellyfin.internal no requiere hardware nuevo, solo clases Coder que ya tienes en la LAN: una Raspberry Pi 4/5 o mini PC 24/7 con AdGuard Home + Nginx Proxy Manager. DHCP reservations para IPs fijas, DNS rewrites para nombres limpios, proxy hosts para esconder puertos. Tres servicios que ya conocés (AdGuard, Nginx, dnsmasq si prefieres) cooperando con una config que tarda un domingo en montar y que después es edit-free.
Lo importante: usa .internal, no .local. ICANN lo reservó permanentemente en 2024 y nunca va a colisionar con un dominio real.
Preguntas frecuentes
¿Por qué Simplifica tu homelab: adiós IPs y puertos, hola .internal hostnames es relevante para sysadmins Linux?
Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.
¿Qué necesito para empezar con Simplifica tu homelab: adiós IPs?
Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.
¿Cuáles son los errores más comunes con Simplifica tu homelab: adiós IPs?
Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.
¿Cuándo usar Simplifica tu homelab: adiós IPs y cuándo una alternativa?
Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.
¿Cómo migro desde una configuración previa a Simplifica tu homelab: adiós IPs?
Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.
Lee también
- Guía Fedora 44: Novedades, Instalación y Upgrade para Sysadmins Linux
- Configura VLANs en Linux con nmcli: Guía paso a paso para sysadmins
- Protege tu SSH: Guía esencial para configurar Fail2ban en Linux
- Guía Definitiva: Configura Kubernetes con kubeadm en Ubuntu para Sysadmins Linux
- Configura Prometheus y Grafana: Guía DevOps para SysAdmins Linux
