PowerDNS

PowerDNS is a DNS server, written in C++ and licensed under the GPL. PowerDNS features a large number of different backends ranging from simple BIND style zonefiles to relational databases and load balancing/failover algorithms.

Installation

Install the powerdns package.

Next you can review the configuration file located at /etc/powerdns/pdns.conf.

Backends

To configure PowerDNS to use specific backend you will need to set the launch option in configuration file. Also depending on particular backend you use, you will have to configure it.

For PostgreSQL, MySQL and SQLite you can find database table creation SQL files located at /usr/share/doc/powerdns.

PostgreSQL backend

Firstly you will need to create a user and database where PowerDNS can store data, then import the schema:

$ psql -U <user> -d <database name> -a -f /usr/share/doc/powerdns/schema.pgsql.sql

And finally update configuration file to use the backend:

/etc/powerdns/pdns.conf
launch=gpgsql
gpgsql-host=/run/postgresql # if PostgreSQL is listening to unix socket
# gpgsql-host=127.0.0.1
# gpgsql-port=5432
gpgsql-dbname=<database name>
gpgsql-user=<user to use>
gpgsql-password=
# Uncomment for dnssec support
#gpgsql-dnssec=yes

MySQL backend

Install and run a MySQL server. Create a new user, and a new database and import the schema into the db:

$ mysql -u root -p pdns < /usr/share/doc/powerdns/schema.mysql.sql

Then, configure Powerdns to use MySQL:

/etc/powerdns/pdns.conf
launch=gmysql
gmysql-host=127.0.0.1
gmysql-socket=/run/mysqld/mysqld.sock
gmysql-user=pdns
gmysql-password=Pa$$w0rd
gmysql-dbname=pdns
# Uncomment for dnssec support
#gmysql-dnssec=yes

You could also use localhost instead of 127.0.0.1, but this causes PowerDNS to use the socket file. As PowerDNS runs in a chroot by default, the socket file is not available.

SQLite backend

Configure Powerdns to use sqlite:

/etc/powerdns/pdns.conf
launch=gsqlite3
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
# Uncomment for dnssec support
#gsqlite3-dnssec=yes

Create the database:

# mkdir /var/lib/powerdns
# sqlite3 /var/lib/powerdns/pdns.sqlite3 < /usr/share/doc/powerdns/schema.sqlite3.sql
# chown -R powerdns:powerdns /var/lib/powerdns

Startup

Start/enable pdns.service.

Zone Management

PowerDNS comes with pdnsutil(1) utility to easily manage hosted zones.

Create a new, empty zone:

[powerdns]$ pdnsutil create-zone example.net

To edit the zone:

[powerdns]$ pdnsutil edit-zone example.net
Note: EDITOR environment variable must be set to be able edit the zone this way.
Warning: When editing the zone, all names must be in fully-qualified form, without trailing dot (e.g. www.example.net).

Upon saving and quitting the editor, you will be asked for confirmation to commit the changes. Carefully read the shown diff and only press a when you're certain that the change is correct. If you keep SOA record unchanged, you'll also be asked whether to increase serial number or not. In most cases, you can simply reply with y, which bumps the number.

When you want to no longer serve the zone, you can remove it from the backend:

[powerdns]$ pdnsutil delete-zone example.net

DNSSEC

PowerDNS has easy-to-use facilities to serve DNSSEC-signed zone with minimal administrative overhead. It takes advantage of online signing architecture, which generates signatures on-demand when queries come from Internet.

For most cases, turning existing insecure zone into DNSSEC-signed one is as simply as:

[powerdns]$ pdnsutil secure-zone example.net

This will sign the zone with single (CSK) ECDSA 256-bit (algorithm 13) key with NSEC denial-of-existence.

For more flexibility on key generation, pdnsutil add-zone-key command can be used instead. For example, to generate traditional KSK/ZSK split ECDSA 256-bit keys:

[powerdns]$ pdnsutil add-zone-key example.net ksk active published ecdsa256
[powerdns]$ pdnsutil add-zone-key example.net zsk active published ecdsa256
[powerdns]$ pdnsutil increase-serial example.net

To view DS records (and other zone information):

[powerdns]$ pdnsutil show-zone example.dns

Submit DS to the parent zone (e.g. by filling the web form on your registrar).

Note: In primary/secondary setup, DNSSEC-signed zones are served as pre-signed zones on secondaries. This can alleviate CPU load on secondaries as these zones' signatures were generated in online signing mode on primary (which can be set up as stealth one) during zone transfer.
Warning: PowerDNS currently doesn't have automatic key management feature. If you want to roll keys, see the upstream guide (for KSK, for ZSK, and for algorithm rollovers) to avoid pitfalls that can cause your zone being bogus.

Tips and Tricks

Bind address and/or port

The default /etc/powerdns/pdns.conf binds to 0.0.0.0:53 (all IP addresses). This will conflict with any other process bound to port 53, for example systemd-resolved uses 127.0.0.53:53. This will result in an error:

Unable to bind UDP socket to '0.0.0.0:53': Address already in use

This can be resolved in a number of ways, for example changing either/both local-address or local-port options:

/etc/powerdns/pdns.conf
local-address=127.0.0.1:54

Zone replication via AXFR (primary/secondary setup)

By default, zones in PowerDNS are native, which means that zone replication is handled by the backend. It is only make sense for MySQL and PostgreSQL backends as they have database replication facility.

You can also configure PowerDNS in classical primary/secondary setup. First, enable appropriate mode in /etc/powerdns/pdns.conf.

On primary:

/etc/powerdns/pdns.conf
primary=yes
allow-axfr-ips=10.20.30.50/32

On secondary:

/etc/powerdns/pdns.conf
secondary=yes
allow-notify-from=10.20.30.40/32

where 10.20.30.40 and 10.20.30.50 are IP addresses of primary and secondary, respectively.

Restart pdns.service.

Set the zone type on primary as primary zone:

[powerdns]$ pdnsutil set-kind example.net primary

On secondary, create the secondary zone, specifying primary's IP address to retrieve from:

[powerdns]$ pdnsutil create-secondary-zone example.net 10.20.30.40

The zone will be transferred after a while.

TSIG authentication

You can also authenticate zone transfers with TSIG keys.

On primary, generate hmac-sha256 key:

[powerdns]$ pdnsutil generate-tsig-key example hmac-sha256
Create new TSIG key example <secret>

Enable the key for primary zone's outgoing transfer:

[powerdns]$ pdnsutil activate-tsig-key example.net example primary

On secondary, import the key:

[powerdns]$ pdnsutil import-tsig-key example hmac-sha256 '<secret>'

Enable the key for secondary zone's transfer request:

[powerdns]$ pdnsutil activate-tsig-key example.net example secondary

See also