A while ago I took on the challenge of deploying a brand new DNS server setup on FreeBSD. The requirements of the project demanded a little bit more than what BIND or Unbound could provide, so I settled on PowerDNS coupled with the PowerAdmin web frontend. Once set up, I enjoyed it so much I ended up setting it up on my homelab! (and had to retrace my steps once again).
The trouble with that was however, that there’s very little in the way of documentation for setting up PowerDNS on FreeBSD out there. Any documentation PowerDNS themselves provide at the time of writing in 2026 is woefully incomplete and outdated, and there’s only a couple of blog posts out there that happen to point in the right direction, but are still quite out of date or missing vital steps.
I came up with this solution for deploying this triumvirate on FreeBSD by piecing together various documentation and a lot of trial and error.
This setup makes use of MySQL (boo Oracle boo) as the database backend for both PowerDNS and PowerAdmin. If you would rather use something like Postgresql, feel free to amend the packages you install and the database setup to fit; the general process however should be much the same.
This guide isn’t perfect, but should get you a working basic setup. If you know what you’re doing, you’ll likely want to improve on some of these configurations, or take things further with a secondary PowerDNS server with replication (which isn’t covered here). I am not responsible for any issues or unexpected behaviour or consequences that may arise from following this guide.
Setting up PowerDNS Authoritative Server
Naturally, the first step is installing the prerequisites. Thankfully, PowerDNS is packaged for FreeBSD and is available both as a port and in the repository. Assuming you have an installed base FreeBSD installation with pkg installed, you can start with:
# pkg install powerdns powerdns-recursor mysql84-server bind-tools
If you prefer, you can build from ports:
# cd /usr/ports/dns/powerdns && make install clean
# cd /usr/ports/dns/powerdns_recursor && make install clean
# cd /usr/ports/databases/mysql84-server && make install clean
# cd /usr/ports/dns/bind-tools && make install clean
After that, you’ll want to enable the daemons for all these new services (provided you want them starting at boot).
# sysrc pdns_enable="YES” && service pdns start
# sysrc pdns_recursor_enable=“YES” && service pdns_recursor start
# sysrc mysql_enable="YES” && service mysql-server start
Since we’re using MySQL as the backend for PowerDNS to store all of its DNS records, we’ll need to configure the MySQL server. I recommend starting with:
# mysql_secure_installation
to configure a MySQL root password and set the server up in a more secure state from its defaults. You might find you need to run this twice for some reason to set the root password - I’ve no idea why.
You’ll also want to copy the template MySQL config file to the location for a working one, since MySQL doesn’t create one by default. Feel free to configure MySQL as required; in this case I’m just using the defaults in the template file.
# cp /usr/local/etc/mysql/my.cnf.sample /var/db/mysql/my.cnf
Next, you’ll want to log in to MySQL and create the PowerDNS database, and a user for PowerDNS to interact with the database. Feel free to name the database and user however you wish. Log in with:
# mysql -u root -p
Once logged in, you can set up the database thusly:
> CREATE DATABASE powerdns;
> CREATE USER ‘powerdns_admin`@`localhost` IDENTIFIED BY `nice_secure_password_here`;
> GRANT ALL PRIVILEGES ON powerdns.* TO `powerdns_admin`@`localhost`;
> FLUSH PRIVILEGES;
> EXIT;
Some tutorials you find online would have you now create the PowerDNS DB schema from scratch. Who’s got time for that?!
Thankfully, PowerDNS on FreeBSD comes with schema for all your favourite databases, including MySQL, however there’s no obvious documentation of where they’re located. You’ll find them in /usr/local/share/doc/pdns/ as .sql files. (Note: on FreeBSD 14, this folder is named slightly differently, as /usr/local/share/doc/powerdns/ . Why the difference? I have no idea).
All you need to do is import the schema. You can do that with:
# mysql -u powerdns_admin -p powerdns < /usr/local/share/doc/pdns/schema.mysql.sql
Next, we’ll need to configure the PowerDNS config file so that it can talk to our new shiny database. Open /usr/local/etc/pdns/pdns.conf in your favourite text editor and add/edit the following:
api=yes
# you'll need to add the gmysql stuff to the file
launch=gmysql
gmysql-host=localhost
gmysql-user=powerdns_admin
gmysql-password=YOUR_DATABASE_PASSWORD
gmysql-dbname=powerdns
local-address: <IP_you_want_your_DNS_server_on>, 127.0.0.1 ::
local-port: 5353
# we're changing the port since the recursor will listen on 53 instead
After all that, you’ll need to restart PowerDNS with:
# service pdns restart
At this point, you should have a working authoritative DNS server! You can test it with dig , for example:
# dig a www.example.com @127.0.0.1
If you did indeed change the port that PowerDNS listens on earlier in pdns.conf , you’ll want to specify the port in the dig command.
# dig a www.example.com @127.0.0.1 -p 5353
If all is working, you should get a response from the server! (Albeit with a status: REFUSED since it does not know about www.example.com).
PowerDNS do have some good documentation on doing some initial testing of your new DNS server by adding some records via pdns pdnsutil, which you can find here, rather than me rehashing it.
Setting up PowerDNS Recursor
Now that you have a working PowerDNS authoritative DNS server, you might want to leave it at that. However, if you want your DNS server to be able to do recursion (i.e., both look up things locally but also on the internet), you’ll want to set up the recursor, which operates as a separate daemon.
This part is really simple for a basic setup. To start, you’ll want to edit the recursor config file. By default the recursor on FreeBSD only comes with a template file, so you’ll want to copy that template file to a working one:
# cp /usr/local/etc/pdns/recursor.yml-dist /usr/local/etc/pdns/recursor.yml
Open that new recursor.yml file and uncomment/edit the following:
listen:
- <IP_you_want_your_DNS_server_on>
port: 53
# the recursor listens on port 53 and forwards the requests to the authoritative server on 5353
forward_zones_file: ‘/usr/local/etc/pdns/forward_zones.conf’
You’ll have noticed we’ve added a “forward zones file” to the config. This file will tell the recursor which DNS zones we want requests to be forwarded for, and where to forward them to. For a simple setup where any requests for any zone PowerDNS is authoritative for are forwarded to the local authoritative server, you can set it up like this:
+yourdomainname.com=127.0.0.1:5353
+168.192.in-addr.arpa=127.0.0.1:5353
The above will forward any requests for the yourdomainname.com zone to our local PowerDNS authoritative server listening on port 5353, as well as any reverse lookups. You may want to change the reverse lookup line to reflect whichever RFC1918 IP scheme you use (for this example, I just stuck with 192.168.0.0).
After that, you can restart the recursor with:
# service pdns_recursor restart
and you should have a fully working recursor! You can test it again with dig, something like:
# dig google.com @<IP_you_want_your_DNS_server_on>
and you should get a response from the recursor!
Setting up the PowerAdmin web interface
This guide focuses on running PowerAdmin on Apache 2.4 with PHP 8.4. PowerAdmin provide some documentation for FreeBSD for nginx that you can find here if you prefer (though I can’t vouch for its accuracy). Newer versions of PHP should also work (PHP 8.6 is currently packaged for FreeBSD 15 at the time of writing) but I’ve not tried it.
First you’ll need to install the prerequisites:
# pkg install apache24 php84 mod_php84 php84-session php84-filter php84-gettext php84-intl php84-mbstring php84-tokenizer php84-xml php84-pdo_mysql
There is now a port of PowerAdmin available under dns/poweradmin that you can try if you’re feeling daring and comfortable with ports. It installs most of those prerequisites (except for a web server), however I can’t vouch for it. The web server configuration should be much the same however.
With Apache installed, you’ll want to enable it so it starts on boot:
# sysrc apache24_enable="YES"
You’ll also need to grab the latest release of PowerAdmin from their Github repo. You can just wget that into /usr/local/www/ (or wherever you’d like your web root to be) and untar it. The untarred folder will have the version number in it; if you prefer you can rename it to simply poweradmin.
Once that’s done, you’ll want to give the poweradmin folder to the web server user:
# chown -R www:www /usr/local/www/poweradmin
Next, we need to configure Apache to be able to host PowerAdmin. By default, Apache on FreeBSD isn’t configured to support PHP whatsoever for some strange reason. We installed mod_php84 earlier, which is the module Apache needs to be able to do anything with PHP. Telling Apache to load the PHP module seems to be a step missing from all of the documentation I’ve seen so far.
We need to edit the Apache config at /usr/local/etc/apache24/httpd.conf and add/edit the following:
## Add this line to the bottom of the modules section:
LoadModule php_module libexec/apache24/libphp.so
## Add index.php to the DirectoryIndex
DirectoryIndex index.html index.php
We also need to create a config file in /usr/local/etc/apache24/modules.d/ to tell Apache how to interact with .php files. Create the file /usr/local/etc/apache24/modules.d/001_mod-php.conf and add to it:
<IfModule dir_module>
DirectoryIndex index.php index.html
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch "\.phps$">
SetHandler application/x-httpd-php-source
</FilesMatch>
</IfModule>
Next, we need to add a VirtualHost config to Apache so it knows about PowerAdmin. Create the file /usr/local/etc/apache24/vhost/poweradmin.conf (you may need to create the vhost directory) and add the following:
## /path/to/poweradmin will be wherever your web root is. If you followed earlier,
## it's likely somewhere like /usr/local/www/poweradmin
<VirtualHost *:80>
ServerName poweradmin.local
DocumentRoot /path/to/poweradmin
<Directory /path/to/poweradmin>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
You’ll also want to add this new vhost file as an include to Apache’s httpd.conf, which you can append at the bottom of that file:
Include etc/apache24/vhost/*.conf
All you need to do now is start the Apache server:
# service apache24 start
and provided all went well, PowerAdmin should be running! You can access it by going to a web browser and entering the IP of the server.
PowerAdmin provides a nice installer interface to set it all up with database access and a working configuration file. Rather than walk you through that, I’ll just direct you to their documentation on the installation wizard.
That’s all folks!