Navigate back to the homepage

PowerDNS master-slave cluster

Anatoli Nicolae
December 29th, 2019 · 2 min read

This guide’s purpose is to help you set up a replicated PowerDNS cluster using AXFR notifications between servers instead of full DB replication, which can be tricky to set up some times.

Prerequisites

This guide assumes we have the following 3 servers running on CentOS 7:

HostnameIPTypeOperation Mode
hostmaster.example.com172.16.0.1Mastersupermaster
ns01.example.com192.168.0.1Slave superslave
ns02.example.com192.168.0.2Slave superslave

Note that these local IPs are purely explanatory and you should use your servers’ public IPs instead, if they’re not the same network.

Operation mode on the slave servers is superslave, which allows them to automatically create zones and sync records, while just slave mode will not create new zones. Learn more about superslaves.

Make sure that domains on the Master node have their type set to MASTER, since other values will not notify the slaves. You should use NATIVE when performing a DB replication instead.

Install repos

The first step is to enable EPEL and PowerDNS repos to access all packages needed. We’ll run an update too just to fully have the system up to date.

1yum install -y epel-release yum-plugin-priorities
2curl -o /etc/yum.repos.d/powerdns-auth-42.repo https://repo.powerdns.com/repo-files/centos-auth-42.repo
3yum update -y

Install MariaDB and pdns

We can now install in one shot both MariaDB and PowerDNS’ packages running the following command.

1yum install -y mariadb mariadb-server pdns pdns-backend-mysql

Enable firewall, MariaDB and pdns services

Enable all three services and start them up using --now. PowerDNS may give an error on startup since there are no backends configured yet, but that’s not an issue at this point. We also proceed to add DNS to our firewall rules in order to accept connections on port 53, reloading then the firewall.

1systemctl enable --now firewalld mariadb pdns
2firewall-cmd --add-service=dns --permanent
3firewall-cmd --reload

MariaDB setup

The DB should be up and running now, but we first need to finish the setup running the following command:

1mysql_secure_installation

This will allow us to log in now as root using the password we set above.

1mysql -u root -p

Now that we’re in the DB, we can create powerdns’ database and the user we’ll use to connect to the DB.

1CREATE DATABASE powerdns;
2GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'powerdns';
3FLUSH PRIVILEGES;

Install schema

While still in the DB, we can run the following command to use our newly created DB:

1USE powerdns;

We now have to create the schema that PowerDNS runs on. You can find more about the configuration, and a copy-pastable schema, on PowerDNS’ documentation at the following link:

https://doc.powerdns.com/authoritative/guides/basic-database.html#example-configuring-mysql

Add supermasters

On each of the superslaves we have to define our supermaster (172.16.0.1). To do this, we have to run INSERT a new row on ns01 as following:

1INSERT INTO `powerdns`.`supermasters` (`ip`, `nameserver`) VALUES ('172.16.0.1', 'ns01.example.com');

and the following one on ns02:

1INSERT INTO `powerdns`.`supermasters` (`ip`, `nameserver`) VALUES ('172.16.0.1', 'ns02.example.com');

PowerDNS slave setup

We can now configure pdns to send notification from the master server, and to receive them on the slave servers.

If you already have anything in your configuration, just make a copy of it and possibly merge it later.

1cp /etc/pdns/pdns.conf /etc/pdns/pdns.conf.original

Here’s a master boilerplate configuration which should work, but you may change it to fit your own setup.

1cat > /etc/pdns/pdns.conf <<'EOF'
2# Master
3
4daemon=no
5guardian=no
6setgid=pdns
7setuid=pdns
8
9cache-ttl=20
10launch=gmysql
11webserver-port=8081
12webserver-allow-from=127.0.0.1,::1
13api-key=powerdns123
14expand-alias=no
15webserver=no
16api=True
17include-dir=/etc/pdns/local.d
18resolver=no
19version-string=anonymous
20webserver-address=127.0.0.1
21
22launch=gmysql
23gmysql-host=localhost
24gmysql-dbname=powerdns
25gmysql-user=powerdns
26gmysql-password=powerdns
27gmysql-dnssec=no
28
29default-ttl=60
30dnsupdate=yes
31master=yes
32
33EOF

Here’s a slave boilerplate configuration which should work, but you may change it to fit your own setup.

1cat > /etc/pdns/pdns.conf <<'EOF'
2# Slave
3
4daemon=no
5guardian=no
6setgid=pdns
7setuid=pdns
8
9cache-ttl=20
10expand-alias=no
11webserver=no
12resolver=no
13version-string=anonymous
14
15launch=gmysql
16gmysql-host=localhost
17gmysql-dbname=powerdns
18gmysql-user=powerdns
19gmysql-password=powerdns
20gmysql-dnssec=no
21
22allow-axfr-ips=172.16.0.1/32
23allow-dnsupdate-from=172.16.0.1/32
24allow-notify-from=172.16.0.1/32
25dnsupdate=yes
26master=no
27slave=yes
28superslave=yes
29
30EOF

Note that the Master could also have an active API to receive updates via REST API, which is the default configuration in ApisCP and you should definitely check it out.

Restarting the service shouldn’t give an error anymore, and if you did everything correctly by following this guide obviously, it will all run smoothly!

1systemctl restart pdns

Conclusion

Congratulations! You’ve successfully set up a PowerDNS cluster. You can verify the replication by keeping an eye on the slave databases, which should automatically create new zone and insert records upon master notification.

Here are two one-liners which you may find helpful, such as:

  • all zone renotify:

    1pdns_control list-zones --type master | sed '$d' | xargs -L1 pdns_control notify
  • zone cleanup:

    1pdns_control list-zones --type slave | sed '$d' | xargs -I {} sh -c "host -t SOA {} 172.16.0.1 | tail -n1 | grep -q 'has SOA record' || pdnsutil delete-zone {}"

Are you a PowerDNS guru? Share your insights on similar cluster configuration or any tips you think could help in the comments! It’s not that easy to get this right, and it would be awesome if you could help!

More links:

More articles from hopefully.online

Hunting down the best home server

Building a home server: hunting down the best and cheapest parts to build a solid NAS/Homelab from scratch.

June 11th, 2019 · 3 min read

Replacing heavily worn SSDs

How to correctly swap old SSDs reporting wear and IO issues on a brand new server, without breaking stuff in production.

April 13th, 2020 · 2 min read
© 2019–2020 hopefully.online
Link to $https://twitter.com/HopefullyOnlineLink to $https://github.com/hopefullyonline