2026年11月12日
2026年11月12日
PowerDNS Install and Setup on Ubuntu 24.04: Authoritative and Recursor
This article is a localized edition of the Japanese original. Read the Japanese original
PowerDNS is open-source DNS server software. It is split into two programs with different roles.
| Program | Package | Role |
|---|---|---|
| PowerDNS Authoritative Server | pdns-server |
An authoritative server that answers for the zones (domains) you manage. Records are stored in a database such as SQLite, MySQL or PostgreSQL, or in BIND-style files |
| PowerDNS Recursor | pdns-recursor |
A caching resolver that takes queries from users and walks the DNS on the internet to find the answer |
In this article you install both on Ubuntu 24.04 and build the following setup:
- Authoritative Server: listens on port 5300 of
127.0.0.1and serves the internal zonecorp.internalfrom SQLite - Recursor: listens on port 53, forwards only queries for
corp.internalto the Authoritative Server, and resolves everything else on the internet
.internal is a top-level domain that ICANN reserved for internal networks. The steps were tested with Authoritative Server 5.1.5 and Recursor 5.4.9 (as of October 2026). The differences for an authoritative server for a public domain are explained in a later section.
Install
Ubuntu 24.04's own repository also has pdns-server, but it is the 4.8 series (as of October 2026). PowerDNS recommends the newer packages from its official repository (repo.powerdns.com). Here you install the Authoritative Server 5.1 series and the Recursor 5.4 series from the official repository. Check the latest stable series on repo.powerdns.com and adjust the numbers.
# Install the signing key
sudo install -d /etc/apt/keyrings
curl -fsSL https://repo.powerdns.com/FD380FBB-pub.asc | sudo tee /etc/apt/keyrings/powerdns-pub.asc >/dev/null
# Add the repositories (auth-51 = Authoritative 5.1.x, rec-54 = Recursor 5.4.x)
echo "deb [signed-by=/etc/apt/keyrings/powerdns-pub.asc] http://repo.powerdns.com/ubuntu noble-auth-51 main" | sudo tee /etc/apt/sources.list.d/pdns-auth.list
echo "deb [signed-by=/etc/apt/keyrings/powerdns-pub.asc] http://repo.powerdns.com/ubuntu noble-rec-54 main" | sudo tee /etc/apt/sources.list.d/pdns-rec.list
# Prefer the official repository over Ubuntu's own packages
printf 'Package: pdns-*\nPin: origin repo.powerdns.com\nPin-Priority: 600\n' | sudo tee /etc/apt/preferences.d/pdns
sudo apt update
sudo apt install pdns-server pdns-backend-sqlite3 sqlite3 pdns-recursor
Check the installed versions as follows. apt-cache policy also shows that the version from the official repository (repo.powerdns.com) was selected.
pdns_server --version 2>&1 | grep 'PowerDNS Authoritative'
pdns_recursor --version 2>&1 | grep 'PowerDNS Recursor'
apt-cache policy pdns-server pdns-recursor
On Ubuntu, systemd-resolved uses port 53 on 127.0.0.53. To avoid clashing with the addresses PowerDNS listens on, this article sets the listen addresses explicitly. You can see which programs use port 53 with sudo ss -lunpt 'sport = :53'.
Configure the Authoritative Server
Where the configuration lives
The configuration is /etc/powerdns/pdns.conf plus the files under /etc/powerdns/pdns.d/ that it includes. Right after installation, only include-dir=/etc/powerdns/pdns.d and launch= are active in pdns.conf, and pdns.d/bind.conf contains a setup that uses BIND-style files. This article uses SQLite, so move bind.conf out of the way.
sudo mv /etc/powerdns/pdns.d/bind.conf /etc/powerdns/bind.conf.disabled
Create the SQLite database
The table definitions (the schema) ship with the pdns-backend-sqlite3 package.
sudo mkdir -p /var/lib/powerdns
sudo sqlite3 /var/lib/powerdns/pdns.sqlite3 < /usr/share/doc/pdns-backend-sqlite3/schema.sqlite3.sql
sudo chown -R pdns:pdns /var/lib/powerdns
SQLite also writes to the directory that holds the database file, so make the whole directory owned by pdns, the user PowerDNS runs as.
Write the configuration
Create /etc/powerdns/pdns.d/local.conf.
# Backend (SQLite)
launch=gsqlite3
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
# Listen address (127.0.0.1 port 5300, since the Recursor runs on the same server)
local-address=127.0.0.1
local-port=5300
# Default SOA for new zones (@ is replaced by the zone name)
default-soa-content=ns1.@ hostmaster.@ 0 10800 3600 604800 3600
Without default-soa-content, the primary server name in the SOA of a new zone becomes a.misconfigured.dns.server.invalid. After writing the configuration, restart the service and check its status.
sudo systemctl restart pdns
systemctl status pdns
If you query before creating any zone, you get REFUSED because the server does not manage that name. This is expected.
dig @127.0.0.1 -p 5300 test.corp.internal A +norec | grep status
Add a zone and records
Use pdnsutil. PowerDNS 5.0 changed the command syntax of pdnsutil to forms such as pdnsutil zone create and pdnsutil rrset add (5.1 still accepts the older forms such as create-zone). Because the commands write to SQLite, run them as the pdns user.
# Create the zone (one NS record is also created)
sudo -u pdns pdnsutil zone create corp.internal ns1.corp.internal
# Add records (name type TTL content)
sudo -u pdns pdnsutil rrset add corp.internal ns1.corp.internal A 3600 192.0.2.53
sudo -u pdns pdnsutil rrset add corp.internal www.corp.internal A 300 192.0.2.10
sudo -u pdns pdnsutil rrset add corp.internal corp.internal MX 3600 '10 mail.corp.internal'
# Check for errors and show the contents
sudo -u pdns pdnsutil zone check corp.internal
sudo -u pdns pdnsutil zone list corp.internal
With the 4.8 series from Ubuntu's own repository, the commands are pdnsutil create-zone corp.internal ns1.corp.internal, pdnsutil add-record corp.internal www A 300 192.0.2.10, pdnsutil check-zone and pdnsutil list-zone.
To tell the running Authoritative Server about the new zone, make it reload its list of zones.
sudo pdns_control rediscover
Query it to check. If the flags include aa (authoritative answer), the Authoritative Server is answering for its own zone.
dig @127.0.0.1 -p 5300 www.corp.internal A +norec +short
dig @127.0.0.1 -p 5300 www.corp.internal A +norec | grep flags
If you queried the same name just before, an old answer such as REFUSED may come back from the cache. In that case, wait a little and query again.
Configure the Recursor
Recursor 5.x uses YAML configuration files. From 5.2 on, YAML is the default, and the old key=value format is read only with --enable-old-settings. In the packages from the official repository, /etc/powerdns/recursor.conf already contains YAML. Rewrite it as follows.
dnssec:
trustanchorfile: /usr/share/dns/root.key
# Exclude the internal zone, which has no DNSSEC signatures, from validation
negative_trustanchors:
- name: corp.internal
reason: internal zone without DNSSEC
recursor:
hint_file: /usr/share/dns/root.hints
include_dir: /etc/powerdns/recursor.d
# Forward only corp.internal to the Authoritative Server
forward_zones:
- zone: corp.internal
forwarders:
- 127.0.0.1:5300
incoming:
# Addresses to listen on, and clients allowed to query
listen:
- 127.0.0.1
allow_from:
- 127.0.0.0/8
outgoing:
sudo systemctl restart pdns-recursor
systemctl status pdns-recursor
dig @127.0.0.1 www.corp.internal A +short
dig @127.0.0.1 wordpress.org A +short
If the first query returns 192.0.2.10 and the second returns addresses for wordpress.org, both forwarding of the internal zone and resolution on the internet are working.
Key points of the configuration:
- negative_trustanchors: The Recursor validates DNSSEC by default. When it forwards an internal zone without signatures, validation can fail (Bogus) and return
SERVFAIL(in our test environment,www.corp.internalreturnedSERVFAILwithout this entry). List internal zones here to exclude them from validation. - listen and allow_from: To let other PCs on your network use it, add the server's LAN address (for example
192.168.1.10) tolistenand the LAN range (for example192.168.1.0/24) toallow_from. If you openallow_fromto the whole internet, it becomes a resolver anyone can use (an open resolver) and can be abused for DNS-based attacks. - If you have a configuration in the old format,
rec_control show-yamlprints it converted to YAML.
Enable the API (optional)
The Authoritative Server can manage zones and records over an HTTP API. If you use it from an admin panel or external tools, add the following to /etc/powerdns/pdns.d/local.conf.
api=yes
api-key=REPLACE_WITH_A_LONG_RANDOM_STRING
webserver=yes
webserver-address=127.0.0.1
webserver-port=8081
webserver-allow-from=127.0.0.1
sudo systemctl restart pdns
curl -s -H 'X-API-Key: YOUR_API_KEY' http://127.0.0.1:8081/api/v1/servers/localhost/zones
The API can change your zones, so limit webserver-address and webserver-allow-from to the addresses you manage from, and do not expose it to the internet. You can generate a key with, for example, openssl rand -base64 32.
Running an authoritative server for a public domain
To act as the authoritative server for a domain published on the internet (for example example.com), the main changes are:
- Set
local-addressto the server's public IP address, and use the default port 53 forlocal-port(remove thelocal-portline) - Open port 53 for both UDP and TCP in the firewall
- Use your own domain as the zone name, and give real values for the primary server name and administrator address in
default-soa-content - At the registrar where the domain is registered, change the name servers to this server's name. If the name server name is inside the same domain (for example
ns1.example.com), glue records must also be registered - If a single server stops, the names can no longer be resolved, so run two or more authoritative servers
An authoritative server for a public domain does not need the Recursor. Avoid exposing an authoritative server and a caching resolver on the same public address.
Summary
- PowerDNS ships the authoritative server (
pdns-server) and the caching resolver (pdns-recursor) as separate programs - On Ubuntu 24.04, install from the official repository (repo.powerdns.com) and prefer it with
Pin-Priority - For the Authoritative Server, move
pdns.d/bind.confaside and run it withlaunch=gsqlite3and the SQLite schema. In 5.x, create zones withpdnsutil zone createandpdnsutil rrset add, then reload withpdns_control rediscover - Recursor 5.x is configured in YAML. Forward internal zones with
forward_zonesand exclude them from DNSSEC validation withnegative_trustanchors - Limit
allow_fromand the API listen address to what you need
Related articles
- Authoritative DNS vs. caching DNS: roles, the resolution flow, and telling them apart with dig
- How to install BIND and configure a DNS server (basic authoritative setup)
- How to investigate DNS records with dig: reading the output and common patterns
- Mixed internal and external DNS: why a site only fails inside the office or names resolve intermittently
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)