PowerDNS 3.2: First Steps

I have been an avid PowerDNS Authoritative Server (hereafter referred to as PowerDNS – there is also a separate Recursor available that we shall ignore for now – both available at http://www.powerdns.com) user since early in the 2.x series of releases. I replaced a global BIND infrastructure with PowerDNS for many reasons – instant provisioning to an easily replicated MySQL backend being the main one. PowerDNS is also RFC-compliant, powerful, and reliable.

The infrastructure I commissioned served well over 200,000 zones across three nameserver sites – each site receiving well over 100,000,000 queries per day. Two servers at each site, each with their own MySQL backend, replicated to from a hidden MySQL master to which we provisioned, handled this load with ease. Of course, this will depend entirely on the server specifications you use to host PowerDNS. PowerDNS offers support for multiple backends, however MySQL suits my needs well – I’m familiar with it, it’s more suited to DNS provisioning than LDAP (IMHO) and supports native replication (unlike PostgreSQL).

Rather than hacking a provisioning solution around BIND 9, moving to PowerDNS provided a technical advantage as well as a business advantage – customers could have their DNS data provisioned near-instantly – something that BIND 9 with a large number of zones and a cron’d rndc reconfig/reload would not achieve. PowerDNS 3.x introduces support for DNSSEC, something PowerDNS 2.x didn’t have – so it’s time to move to PowerDNS 3.x where possible.

I will use this article to walk through an installation of PowerDNS 3.2 from source on CentOS 6.3, perform basic configuration, load a basic zone, and serve the zone data authoritatively. This article will only scrape the surface of what PowerDNS has to offer, and further articles will be written in due course to cover interesting concepts in finer detail.

Have a good read over the manual available on the PowerDNS documentation site (http://doc.powerdns.com) too.

Preparation

Whilst not really required for a lab/test installation, I will chroot PowerDNS for security. In order to do this, I’ll create a dedicated logical volume to house the chroot. As I use VMware for all lab/test installs, I can add a new disk to an existing VM with ease. Whilst LVM and associated filesystem concepts are beyond the scope of a PowerDNS article, I’ll show you how I created the chroot filesystem for completeness. I added a new disk to the VM, which was presented as /dev/sdb.

First step – partition the disk with a single primary partition of type 8e (Linux LVM) spanning the entire disk:

Next, create an LVM physical volume using this newly created partition:

Create a new volume group, vg_data, utilising this PV:

Then create a 5GB logical volume in the vg_data VG:

Create an ext4 filesystem on the new logical volume:

Create a directory for the mountpoint:

Add an entry to /etc/fstab:

Mount the filesystem, and verify:

Software Installation

Presuming that you’ve installed a Minimal CentOS 6.3 installation, install the required prerequisite packages as follows:

Compile PowerDNS 3.2. This assumes that you’ve placed the source tarball under /usr/local/src:

Note that we enable the gmysql module – which will compile in MySQL support and allow backend database connectivity. PowerDNS is installed to /usr/local/pdns-3.2,/usr/local/<somepackage>-<version>, being my preferred installation location for custom software. Don’t get me on an /opt rant; it’s lame, like /srv. But … I digress. I create a symlink back to the versioned software from /usr/local/<somepackage>. This enables very simple upgrades: compile and install the new software revision, stop the software, change the link to point to the new installation, start the software. Rollback is obviously just as easy as it’s the reverse procedure.

Software Configuration

Populate the base MySQL system tables, and configure MySQL to start on server reboot:

Start MySQL:

Set the MySQL root password and verify that you can connect:

Add a user and group for PowerDNS. This is a security feature present in most good software nowadays that needs to bind to a privileged port. PowerDNS will drop privileges down to the user and group we create here once it’s bound (and configured within PowerDNS):

And chown our chroot:

Edit /usr/local/pdns/etc/pdns.conf as follows (whilst reading the documentation available on the PowerDNS site so that you understand what is going on):

Fairly self-explanatory but the main points to note are that we’re chrooting PowerDNS and dropping privileges as previously detailed, daemonising, acting as a master, and using the MySQL backend. ALWAYS use gmysql – the older mysql backend is no longer supported and will not work as expected. Ensure that the file is locked down as it contains the PowerDNS user’s MySQL password in clear text:

There are many more configuration variables available for customisation and I suggest you read up thoroughly on what they do. A lot of them can change the way PowerDNS handles requests (out-of-zone data, for example) or can impact performance. Do not steer away from the defaults unless you know what you are doing.

Starting PowerDNS for the First Time

Even though we haven’t created the backend database yet, let’s start PowerDNS and see what happens. We’ll configure PowerDNS to start via a script in /etc/init.d soon enough – for now just start it up:

Kaboom! Expected, but good to see that our compile and install were successful, and the gmysql backend works.

Database Creation

Create a database and MySQL user using the same credentials and database name entered into the various gmysql-* variables in /usr/local/pdns/etc/pdns.conf:

The sample MySQL schema is provided in the PowerDNS Manual (same documentation link as before – Section 4). Connect as our newly created pdns user, and apply the schema:

This article is not a discussion of MySQL, and if you don’t understand the above you should consult a good MySQL tutorial to get a grasp of the foundations of both MySQL and SQL itself.

Startup and Verification

PowerDNS should still be running, so kill it, and start it up again:

It’s worth noting here that PowerDNS has correctly dropped the privileges down to the pdns user as configured.

Checking /var/log/messages shows the successful startup:

Verify the installation with a query for version.bind:

Good – it works. I don’t like all that information being exposed, however, so I’ll modify the version-string parameter in pdns.conf and restart:

Try the query again:

Perfect. To verify the server is running, you can also send it a ping, to which you should receive a PONG. No PONG == bad:

Loading Your First Zone

Let’s load trusty example.com into the database. zone2sql, provided with PowerDNS, will read RFC-compliant zonefiles and convert them to MySQL statements. So we can see what’s going on, I’ll execute the SQL statements manually (presuming you’re connected to the database via the MySQL monitor already):

Run some queries and verify that all is well:

Provisioned near-instantly – this is a good thing and this is why I moved away from BIND for high-demand and highly-variable customer-driven DNS hosting. All that pointing and clicking (and of course sanity checking and verifying somewhere in the middleware before committing blindly to the database at a user’s complete whim) can lead to a lot of changes on the backend.

Finishing Up

Let’s stop PowerDNS again, and configure the /etc/init.d script so that it’s properly started upon reboot under the watchful gaze of a guardian process (run a ps -ef after starting with /etc/init.d/pdns to see what I mean) – the guardian will restart pdns_server-instance if it fails:

Note that the /etc/init.d script is configured and provided at software build time.

It’s worth also noting that /etc/init.d/pdns dump will provide a lot of useful (and parseable) information about the instance (I’ll run a query to bump the counters):

Conclusion

This article has illustrated how to install and configure a basic PowerDNS instance serving authoritative DNS data. You can see how simple it’d now be to replicate the MySQL database to another server, and another PowerDNS instance, and quickly provision multiple slave servers.

PowerDNS really is my preferred DNS server for DNS hosting. For Corporate DNS, both internal and external, I still prefer BIND 9.

Stay tuned to tokiwinter.com for more articles around DNS servers, particularly PowerDNS, BIND 10 and DNSSEC.