--- title: "Cómo instalar PowerDNS con MySQL en Ubuntu 24.04" description: "Instala PowerDNS Authoritative Server con backend MySQL en Ubuntu 24.04, crea zonas y registros con pdnsutil, activa la API REST y firma tus zonas con DNSSEC." category: "DNS Avanzado" language: es source: https://cubepath.com/es/docs/dns-avanzado/instalacion-y-configuracion-de-powerdns updated: 2026-09-25 --- # Cómo instalar PowerDNS con MySQL en Ubuntu 24.04 PowerDNS Authoritative Server es un servidor DNS autoritativo de código abierto que guarda las zonas en una base de datos en lugar de en ficheros de texto, lo que permite gestionarlas con una herramienta de línea de comandos (`pdnsutil`) o con una API REST. En este tutorial instalarás PowerDNS con backend MySQL en Ubuntu 24.04, crearás una zona con sus registros, activarás la API para automatizar cambios y firmarás la zona con DNSSEC. Un servidor autoritativo responde por los dominios que tú alojas. No resuelve nombres de Internet para tus clientes: para eso necesitas un resolvedor recursivo como Unbound. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS y una IP pública, por ejemplo un VPS de CubePath. Para producción conviene tener dos servidores (`ns1` y `ns2`), pero este tutorial usa uno. - Un usuario no root con privilegios `sudo`. - Al menos 1 GB de RAM. - Un dominio cuyo DNS vayas a delegar en este servidor. En los ejemplos se usa `your_domain` y la IP `your_server_ip`; sustitúyelos por los tuyos. - Acceso al panel de tu registrador para crear los registros *glue* de `ns1.your_domain` y, más adelante, publicar el registro DS de DNSSEC. ## Paso 1: Liberar el puerto 53 En Ubuntu 24.04, `systemd-resolved` ocupa el puerto 53 en `127.0.0.53` con su *stub listener*. PowerDNS escucha por defecto en todas las direcciones (`0.0.0.0` y `::`), así que ambos chocarían. Desactiva el stub listener con un fichero de configuración adicional: ```bash sudo mkdir -p /etc/systemd/resolved.conf.d sudo nano /etc/systemd/resolved.conf.d/no-stub.conf ``` Añade este contenido: ```ini [Resolve] DNSStubListener=no ``` Apunta `/etc/resolv.conf` al fichero que contiene los resolvedores reales (los que recibe el servidor por DHCP o netplan) y reinicia el servicio: ```bash sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf sudo systemctl restart systemd-resolved ``` Comprueba que nada escucha ya en el puerto 53 y que el servidor sigue resolviendo nombres: ```bash sudo ss -lntup 'sport = :53' getent hosts cubepath.com ``` El primer comando no debe mostrar ningún socket y el segundo debe devolver una IP. ## Paso 2: Instalar MySQL y PowerDNS Ubuntu 24.04 incluye PowerDNS 4.8 en sus repositorios, una versión estable y con soporte de seguridad del propio Ubuntu. Instala el servidor, el backend MySQL y el servidor MySQL: ```bash sudo apt update sudo apt install mysql-server pdns-server pdns-backend-mysql ``` Verifica la versión instalada con `apt`: ```bash apt policy pdns-server | head -n 3 ``` ```output pdns-server: Installed: 4.8.3-4build3 Candidate: 4.8.3-4build3 ``` > Nota: si necesitas una versión más reciente, PowerDNS publica repositorios oficiales en `repo.powerdns.com`. Para la mayoría de instalaciones, el paquete de Ubuntu es suficiente y se actualiza con `apt upgrade`. El paquete puede arrancar PowerDNS con el backend BIND de ejemplo. Detén el servicio mientras lo configuras: ```bash sudo systemctl stop pdns ``` ## Paso 3: Crear la base de datos En Ubuntu, el usuario `root` de MySQL se autentica por socket, así que puedes entrar con `sudo` sin contraseña: ```bash sudo mysql ``` Crea la base de datos y un usuario dedicado. Sustituye `your_strong_password` por una contraseña larga y aleatoria (por ejemplo, la salida de `openssl rand -base64 24`): ```sql CREATE DATABASE pdns CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'pdns'@'localhost' IDENTIFIED BY 'your_strong_password'; GRANT ALL PRIVILEGES ON pdns.* TO 'pdns'@'localhost'; EXIT; ``` Importa el esquema que incluye el paquete `pdns-backend-mysql`: ```bash sudo mysql pdns < /usr/share/pdns-backend-mysql/schema/schema.mysql.sql ``` Comprueba que se han creado las tablas: ```bash sudo mysql pdns -e "SHOW TABLES;" ``` ```output +----------------+ | Tables_in_pdns | +----------------+ | comments | | cryptokeys | | domainmetadata | | domains | | records | | supermasters | | tsigkeys | +----------------+ ``` ## Paso 4: Configurar el backend MySQL El fichero principal `/etc/powerdns/pdns.conf` carga todo lo que haya en `/etc/powerdns/pdns.d/`. Si el paquete del backend BIND está instalado, habrá un `bind.conf` en ese directorio; quítalo para que PowerDNS use solo MySQL: ```bash sudo rm -f /etc/powerdns/pdns.d/bind.conf ``` Crea la configuración del backend: ```bash sudo nano /etc/powerdns/pdns.d/gmysql.conf ``` ```ini launch=gmysql gmysql-host=127.0.0.1 gmysql-port=3306 gmysql-dbname=pdns gmysql-user=pdns gmysql-password=your_strong_password gmysql-dnssec=yes ``` El fichero contiene la contraseña de la base de datos, así que limita quién puede leerlo: ```bash sudo chgrp pdns /etc/powerdns/pdns.d/gmysql.conf sudo chmod 0640 /etc/powerdns/pdns.d/gmysql.conf ``` Arranca PowerDNS y habilítalo al inicio: ```bash sudo systemctl enable --now pdns sudo systemctl status pdns --no-pager ``` La salida debe indicar `active (running)`. Si no es así, revisa el log con `sudo journalctl -u pdns -n 50`: un error de conexión a MySQL suele deberse a una contraseña mal copiada en `gmysql.conf`. ## Paso 5: Abrir el firewall DNS usa UDP para la mayoría de consultas y TCP para respuestas grandes y transferencias de zona. Permite ambos en el puerto 53, además de SSH: ```bash sudo ufw allow OpenSSH sudo ufw allow 53 sudo ufw enable sudo ufw status ``` ```output To Action From -- ------ ---- OpenSSH ALLOW Anywhere 53 ALLOW Anywhere ``` ## Paso 6: Crear una zona y sus registros `pdnsutil create-zone` crea la zona con un registro SOA y el NS que le indiques: ```bash sudo pdnsutil create-zone your_domain ns1.your_domain ``` Añade el resto de registros con `pdnsutil add-record ZONA NOMBRE TIPO [TTL] CONTENIDO`. Usa `@` para el propio dominio: ```bash sudo pdnsutil add-record your_domain ns1 A your_server_ip sudo pdnsutil add-record your_domain @ A your_server_ip sudo pdnsutil add-record your_domain www CNAME your_domain. sudo pdnsutil add-record your_domain @ MX "10 mail.your_domain." sudo pdnsutil add-record your_domain mail A your_server_ip sudo pdnsutil add-record your_domain @ TXT '"v=spf1 mx -all"' ``` Revisa la zona y valida que no tenga errores: ```bash sudo pdnsutil list-zone your_domain sudo pdnsutil check-zone your_domain ``` ```output Checked 8 records of 'your_domain', 0 errors, 0 warnings. ``` Consulta el servidor directamente para confirmar que responde con autoridad: ```bash dig @127.0.0.1 your_domain A +norec ``` En la respuesta, la línea de `flags` debe incluir `aa` (*authoritative answer*) y la sección `ANSWER` debe mostrar `your_server_ip`. Cuando edites registros con `pdnsutil edit-zone` o directamente en la base de datos, incrementa el número de serie del SOA para que los secundarios detecten el cambio: ```bash sudo pdnsutil increase-serial your_domain ``` ## Paso 7: Activar la API REST La API permite crear zonas y registros desde scripts, paneles o herramientas como Terraform, sin tocar la base de datos. Genera una clave aleatoria: ```bash openssl rand -hex 32 ``` Crea un fichero de configuración para la API y pega la clave en `api-key`: ```bash sudo nano /etc/powerdns/pdns.d/api.conf ``` ```ini api=yes api-key=your_api_key webserver=yes webserver-address=127.0.0.1 webserver-port=8081 webserver-allow-from=127.0.0.1,::1 ``` La API solo escucha en localhost. Si necesitas usarla desde otra máquina, hazlo a través de un túnel SSH o una red privada, nunca abriendo el puerto 8081 a Internet. Protege el fichero y reinicia: ```bash sudo chgrp pdns /etc/powerdns/pdns.d/api.conf sudo chmod 0640 /etc/powerdns/pdns.d/api.conf sudo systemctl restart pdns ``` Lista las zonas a través de la API: ```bash curl -s -H "X-API-Key: your_api_key" http://127.0.0.1:8081/api/v1/servers/localhost/zones ``` Deberías ver un JSON con `your_domain.` en el campo `name`. Para añadir o sustituir un registro, envía un `PATCH` con un *rrset*. Los nombres van siempre con punto final: ```bash curl -s -X PATCH -H "X-API-Key: your_api_key" \ -H "Content-Type: application/json" \ http://127.0.0.1:8081/api/v1/servers/localhost/zones/your_domain. \ -d '{"rrsets":[{"name":"api.your_domain.","type":"A","ttl":300,"changetype":"REPLACE","records":[{"content":"your_server_ip","disabled":false}]}]}' ``` Una respuesta vacía con código 204 indica éxito. Compruébalo: ```bash dig @127.0.0.1 api.your_domain A +short ``` Para borrar ese registro, repite la petición con `"changetype":"DELETE"` y sin el campo `records`. ## Paso 8: Firmar la zona con DNSSEC DNSSEC añade firmas criptográficas a las respuestas para que los resolvedores puedan detectar respuestas falsificadas. PowerDNS firma las respuestas al vuelo, así que basta con generar las claves: ```bash sudo pdnsutil secure-zone your_domain sudo pdnsutil rectify-zone your_domain ``` Muestra las claves y los registros DS que debes publicar en el registrador: ```bash sudo pdnsutil show-zone your_domain ``` La salida incluye varias líneas `DS = your_domain. IN DS ...` con distintos algoritmos de *digest*. La mayoría de registradores piden la de digest tipo 2 (SHA-256). Comprueba que el servidor ya devuelve firmas: ```bash dig @127.0.0.1 your_domain A +dnssec +norec ``` La respuesta debe incluir un registro `RRSIG` junto al registro `A`. > Importante: publica el registro DS en el registrador solo cuando la delegación (paso siguiente) ya funcione. Si publicas un DS que no coincide con las claves del servidor, los resolvedores que validan DNSSEC devolverán SERVFAIL para todo tu dominio. ## Paso 9: Delegar el dominio Para que Internet use tu servidor, en el panel del registrador: 1. Crea el registro *glue* `ns1.your_domain` apuntando a `your_server_ip` (y `ns2` si tienes un segundo servidor). 2. Cambia los servidores de nombres del dominio a `ns1.your_domain` (y `ns2.your_domain`). 3. Añade el registro DS del paso anterior si activaste DNSSEC. Los cambios en la zona padre pueden tardar horas en propagarse. Verifica la delegación desde fuera con un resolvedor público: ```bash dig your_domain NS @1.1.1.1 +short dig your_domain A @1.1.1.1 +dnssec ``` Cuando el DS esté publicado y sea correcto, la respuesta del segundo comando incluirá el flag `ad`. ## Solución de problemas - **`pdns` no arranca con "Address already in use"**: algo sigue en el puerto 53. Identifícalo con `sudo ss -lntup 'sport = :53'` y revisa el paso 1. - **"Unable to launch gmysql" o errores de conexión**: comprueba los datos de `gmysql.conf` probando la conexión a mano con `mysql -u pdns -p -h 127.0.0.1 pdns`. - **La zona responde REFUSED**: la zona no existe con ese nombre exacto. Lista las zonas con `sudo pdnsutil list-all-zones`. - **Cambios que no aparecen**: PowerDNS cachea las respuestas unos segundos. Espera o vacía la caché de una zona con `sudo pdns_control purge your_domain$`. - **Logs**: `sudo journalctl -u pdns -f` muestra los errores en tiempo real. ## Conclusión Ya tienes PowerDNS funcionando como servidor autoritativo con backend MySQL, una zona firmada con DNSSEC y una API REST local para automatizar cambios. Como siguientes pasos, añade un segundo servidor (`ns2`) en otra ubicación, bien como secundario por AXFR o replicando la base de datos, y automatiza la creación de registros desde tu aplicación o tu herramienta de infraestructura como código usando la API.