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.1 and serves the internal zone corp.internal from SQLite
  • Recursor: listens on port 53, forwards only queries for corp.internal to 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.internal returned SERVFAIL without 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) to listen and the LAN range (for example 192.168.1.0/24) to allow_from. If you open allow_from to 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-yaml prints 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-address to the server's public IP address, and use the default port 53 for local-port (remove the local-port line)
  • 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.conf aside and run it with launch=gsqlite3 and the SQLite schema. In 5.x, create zones with pdnsutil zone create and pdnsutil rrset add, then reload with pdns_control rediscover
  • Recursor 5.x is configured in YAML. Forward internal zones with forward_zones and exclude them from DNSSEC validation with negative_trustanchors
  • Limit allow_from and the API listen address to what you need

Related articles

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲