
En este tutorial te voy a enseñar paso a paso y sin saltarnos nada cómo montar Unbound en un NAS TerraMaster (ARM64) usando Docker y Portainer, para que trabaje junto a AdGuard Home en tu Home Assistant.
Así conseguirás un resolutor recursivo puro que dará más privacidad y velocidad a tus consultas DNS.
Sí, AdGuard Home también se puede instalar en Docker y Portainer, pero he preferido hacerlo como complemento oficial de Home Assistant.
¿Por qué? Muy simple: el add-on ya está integrado directamente en Home Assistant, se configura más rápido, se actualiza solo junto con el sistema y me permite tenerlo todo centralizado sin tener que montar contenedores adicionales ni preocuparme por puertos, volúmenes o actualizaciones manuales.
Además, para lo que necesito, el rendimiento es exactamente el mismo que si lo montara en Docker.
¿Se puede instalar Unbound en Home Assistant?
Actualmente, no existe un add-on oficial o mantenido de Unbound para Home Assistant OS o Home Assistant Supervised, lo que significa que no se puede instalar directamente desde la tienda de complementos. Aunque en el pasado hubo versiones no oficiales creadas por la comunidad, hoy en día la opción más sólida y mantenible es instalar Unbound en un equipo externo, como un NAS o un servidor con Docker y Portainer. De esta forma, Home Assistant puede seguir ejecutando AdGuard Home como complemento oficial y utilizar Unbound como su servidor DNS ascendente. Esta arquitectura no solo garantiza un mejor rendimiento y estabilidad, sino que también evita problemas de compatibilidad o mantenimiento que podrían surgir con soluciones no soportadas oficialmente.
Contexto del proyecto
Actualmente, en Home Assistant OS/Supervised ya no existe un add-on oficial o mantenido de Unbound, así que lo más fiable es instalarlo en otro equipo, en mi caso, el NAS TerraMaster.
La arquitectura final será así:
Clientes → AdGuard Home (HA 192.168.100.50) → Unbound (NAS 192.168.100.60) → Servidores raíz DNS
(Cambia las IPs por las tuyas —comentado en el código más abajo)
AdGuard seguirá filtrando y enviará las consultas a Unbound, que resolverá directamente desde los servidores raíz, sin pasar por DNS de terceros.
Requisitos previos
- NAS TerraMaster F2-212 (CPU ARM64) con Portainer ya instalado.
- Puerto 53 TCP/UDP libre en el NAS (si otro servicio lo usa, Unbound no arrancará).
- IPs fijas:
- NAS (Unbound):
192.168.100.60
← #cambiar esta ip para la de tu NAS - Home Assistant (AdGuard):
192.168.100.50
← #cambiar esta ip para la de tu Home Assistant
- NAS (Unbound):
- Imagen Docker:
ghcr.io/klutchell/unbound:latest
(multi-arch compatible ARM64).
📂 1. Crear carpeta de configuración en el NAS
En tu NAS, crea esta carpeta para guardar los archivos de configuración de Unbound:
/Volume1/DockerAppsData/unbound
Dentro de esa carpeta vamos a crear tres archivos:
a) unbound.conf
Este será el archivo principal de configuración (lo pongo completo más abajo).
b) root.hints
Como en TerraMaster no había curl
ni wget
, descárgalo desde tu PC:
- Abre: https://www.internic.net/domain/named.root
- Guarda el archivo como root.hints
- Sube el archivo a
/Volume1/DockerAppsData/unbound/
c) root.key
Archivo vacío.
En el explorador de archivos, crea un archivo nuevo y llámalo root.key
(sin contenido).
⚙ 2. Configuración probada de Unbound
Guarda este contenido en /Volume1/DockerAppsData/unbound/unbound.conf
:
server:
# logs visibles en Portainer
use-syslog: no
verbosity: 2
# usuario y carpeta válidos en la imagen
username: "unbound"
directory: "/opt/unbound"
# seguridad / privacidad
hide-identity: yes
hide-version: yes
harden-glue: yes
harden-dnssec-stripped: yes
qname-minimisation: yes
rrset-roundrobin: yes
# DNSSEC
auto-trust-anchor-file: "/opt/unbound/root.key"
# caché / rendimiento
msg-cache-size: 50m
rrset-cache-size: 100m
cache-min-ttl: 60
cache-max-ttl: 86400
prefetch: yes
prefetch-key: yes
# escucha
interface: 0.0.0.0
port: 53
do-ip4: yes
do-ip6: no
do-udp: yes
do-tcp: yes
# permisos (tu LAN)
access-control: 127.0.0.1/32 allow
access-control: 192.168.86.0/24 allow
access-control: 0.0.0.0/0 refuse
# root hints (resolución desde raíz)
root-hints: "/opt/unbound/root.hints"
# nombres locales útiles
local-zone: "lan." static
local-data: "nas.lan. IN A 192.168.86.104"
local-zone: "local." static
local-data: "homeassistant.local. IN A 192.168.86.70"
Importante: No hay forward-zone:
— esto es recursivo puro.
2.1. ¿Y si yo tengo AdGuard en Docker?
Si utilizas AdGuard Home en Docker y Portainer en lugar de como complemento de Home Assistant, no necesitas incluir la línea:
local-data: "homeassistant.lan. IN A 192.168.100.50" #cambiar esta ip para la de tu Home Assistant
Esta línea solo es necesaria si Home Assistant (y, por tanto, AdGuard) están en otro dispositivo de tu red y quieres que Unbound resuelva su nombre interno (homeassistant.lan
).
Si todo está dentro del mismo sistema o no usas este nombre local, puedes omitirla sin problema.
Te lo explico claro:
- Esa línea en
unbound.conf
crea un registro DNS local que asociahomeassistant.lan
a la IP que le indiques. - En tu caso es útil porque AdGuard está en Home Assistant, y quieres que Unbound pueda resolver ese dominio local.
- Si AdGuard y Unbound están en el mismo servidor o si el usuario no usa un dominio local personalizado para Home Assistant, se puede omitir sin problema.
- En cambio, si alguien quiere que desde cualquier equipo de la red se pueda escribir
homeassistant.lan
y abrir el panel de HA, sí debería dejarla y ajustar la IP.
2.2. Dominios internos opcionales
En algunos casos puede ser útil añadir entradas extra en local-data
para acceder fácilmente a dispositivos de tu red usando nombres personalizados en lugar de direcciones IP. Esto es completamente opcional:
- No es necesario si el propio dispositivo ya resuelve su dominio interno (por ejemplo,
www.asusrouter.com
en routers ASUS). - Sí es útil si quieres un acceso más corto o uniforme, como
router.lan
onas.lan
, o si el dispositivo no ofrece su propio nombre DNS.
Ejemplos de entradas opcionales en unbound.conf
:
Unbound no solo resuelve dominios públicos, también puede asignar nombres personalizados a dispositivos de tu red local.
Esto se hace con dos directivas:
local-zone
: define un “área” de dominios que Unbound gestionará directamente sin preguntarlo fuera.local-data
: dentro de esa zona, asigna un nombre concreto a una IP.
Por ejemplo:
local-zone: "lan." static
local-data: "nas.lan. IN A 192.168.86.104"
local-zone: "local." static
local-data: "homeassistant.local. IN A 192.168.86.70"
Con esto:
- Si escribes nas.lan en tu navegador, te abre la interfaz del NAS.
- Si escribes homeassistant.local, accedes a Home Assistant.
💡 Truco: no uses .local
si ya usas mDNS en tu red, puede dar conflictos; .lan
es más “seguro”.
💡 Consejo: Si usas dispositivos que ya tienen un dominio propio que funciona (como www.asusrouter.com
), no es necesario añadirlos. Esta técnica es principalmente para nombres personalizados o para dispositivos que no publican su propio dominio.
🐳 3. Despliegue en Portainer (Stack)
En Portainer → Stacks → Add stack, pega este docker-compose.yml
:
version: "3.8"
services:
unbound:
image: ghcr.io/klutchell/unbound:latest
platform: linux/arm64
container_name: unbound
restart: unless-stopped
network_mode: "host"
volumes:
- /Volume1/DockerAppsData/unbound:/opt/unbound
cap_add:
- NET_BIND_SERVICE
# quita el healthcheck si te da guerra
# healthcheck:
# test: ["CMD", "drill", "@127.0.0.1", "com", "NS"]
# interval: 30s
# timeout: 5s
# retries: 5
Pulsa Deploy the stack.
Si puedes, marca Re-pull image and redeploy para asegurarte de que usa la última versión.
🔍 4. Comprobar que Unbound arranca
En Containers → unbound → Logs deberías ver algo como:
[1547824586] unbound[1:0] notice: init module 0: validator
[1547824586] unbound[1:0] notice: init module 1: iterator
[1547824586] unbound[1:0] info: start of service (unbound 1.23.1).
[1547824586] unbound[1:0] info: generate keytag query _ta-4c43-9268. NULL IN
[1547824586] unbound[1:0] info: generate keytag query _ta-4c43-9268. NULL IN
Si no hay errores de root.hints not found
o address already in use :53
, todo va bien.
🧪 5. Probar que resuelve
Además de probar dominios públicos, conviene comprobar que Unbound resuelve también los nombres internos que has configurado con local-data
. Esto asegura que la parte de DNS local está bien. Desde tu PC abre PowerShell (en Windows):
nslookup tecnoyfoto.com 192.168.86.104 #cambiar esta ip para la de tu NAS
nslookup homeassistant.local 192.168.86.104
El segundo comando debería devolver la IP local de tu Home Assistant.
6. Cómo utilizar Unbound en tu red doméstica
Una vez que Unbound está funcionando, tienes dos formas principales de integrarlo en tu red, dependiendo de si usas Home Assistant con AdGuard Home o no:
6.1 Usar solo Unbound (sin AdGuard)
Esta opción es ideal si:
- No usas Home Assistant.
- Quieres aprovechar el NAS para tener un DNS recursivo local.
- Buscas simplicidad y baja latencia, sin filtrado de anuncios.
Cómo configurarlo:
- Entra en la configuración de tu router.
- Localiza la sección de DNS primario (o Servidor DNS).
- Introduce la IP de tu NAS donde corre Unbound (ej.:
192.168.86.104
). - Deja el DNS secundario vacío o pon otro servidor de confianza (ej.
1.1.1.1
de Cloudflare) como respaldo.
Flujo:
scssCopiarEditarClientes → Unbound (NAS) → Servidores raíz DNS
Ventaja:
- Resolución directa desde servidores raíz, sin intermediarios.
Desventaja:
- No tendrás filtrado de publicidad ni bloqueo de rastreadores.
6.2 Usar Unbound junto a AdGuard Home
Esta opción es la mejor si:
- Usas Home Assistant y quieres el filtrado avanzado de AdGuard Home.
- Deseas mantener control local y privacidad total usando Unbound como resolutor recursivo.
Cómo configurarlo:
- En AdGuard Home → Configuración → DNS → Servidores ascendentes
Introduce la IP de Unbound (192.168.86.104
). - Guarda y prueba que se resuelvan dominios correctamente.
- En el router, pon como DNS primario la IP de AdGuard (ej.:
192.168.86.70
). - No pongas DNS secundario para que todo pase siempre por AdGuard.
Flujo:
Clientes → AdGuard Home (HA) → Unbound (NAS) → Servidores raíz DNS
Ventaja:
- Combinas filtrado de anuncios/rastreadores con resolución directa desde raíz.
Desventaja:
- Ligeramente más latencia que usar Unbound solo (aunque casi imperceptible).
Sígueme a Youtube
