Power DNS
Install
Install power DNS with SQL server support.
apt update apt full-upgrade apt install pdns-backend-sqlite3 pdns-backend-mysql pdns-server
Stop
systemctl stop pdns
MySQL
Now setup MySQL for power DNS.
Install mariadb
apt install mariadb-server mariadb-client rehash mariadb-secure-installation
Create database and user
mysql CREATE DATABASE pdns CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci; CREATE USER 'pdns'@'localhost' IDENTIFIED BY 'pdns'; GRANT ALL PRIVILEGES ON pdns.* TO 'pdns'@'localhost'; FLUSH PRIVILEGES; SELECT User,Host FROM mysql.user; +-------------+-----------+ | User | Host | +-------------+-----------+ | mariadb.sys | localhost | | mysql | localhost | | pdns | localhost | | root | localhost | +-------------+-----------+ 4 rows in set (0.002 sec) exit
Create tables
mysql -updns -ppdns pdns < /usr/share/doc/pdns-backend-mysql/schema.mysql.sql
Show tables
mysql -updns -ppdns pdns Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 22 Server version: 11.8.2-MariaDB-1 from Debian -- Please help get to 10k stars at https://github.com/MariaDB/Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [pdns]> show tables; +----------------+ | Tables_in_pdns | +----------------+ | comments | | cryptokeys | | domainmetadata | | domains | | records | | supermasters | | tsigkeys | +----------------+ 7 rows in set (0.001 sec)
Example
Domains
Example domain.
INSERT INTO domains (id,name,type) values (1,'example.com','MASTER');
Domain type can be MASTER, SLAVE or NATIVE (NATIVE does not automatically sync with slaves).
Records
Example records.
You may replace “999” with a serial number generated like this:
php -r 'print time() . "\n";'
INSERT INTO records (domain_id,name,type,prio,content,ttl) VALUES (1,'example.com','SOA',0,'ns1.example.com hostmaster.example.com 999 10800 10800 108000 1800',1800); INSERT INTO records (domain_id,name,type,prio,content,ttl) VALUES (1,'example.com','NS',0,'ns1.example.com',10800);
Configuration
local-address=127.0.0.1,::1 #### MYSQL CONFIG launch=gmysql gmysql-host=localhost gmysql-port=3306 gmysql-dbname=pdns gmysql-user=pdns gmysql-password=pdns gmysql-dnssec=no #### AXFR CONFIG disable-axfr=no allow-axfr-ips=127.0.0.1,::1 #### SECURITY setuid=pdns setgid=pdns #### MASTER primary=yes #### SLAVE secondary=no #### LOGGING loglevel=4 query-logging=no log-dns-details=no #### TTL default-ttl=900
Run
systemctl start pdns
Test
dig ANY example.com @::1 ; <<>> DiG 9.20.11-4-Debian <<>> ANY example.com @::1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7985 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;example.com. IN ANY ;; ANSWER SECTION: example.com. 10800 IN NS ns1.example.com. example.com. 1800 IN SOA ns1.example.com. hostmaster.example.com. 999 10800 10800 108000 1800 ;; Query time: 0 msec ;; SERVER: ::1#53(::1) (TCP) ;; WHEN: Wed Sep 03 20:42:25 BST 2025 ;; MSG SIZE rcvd: 113
dig AXFR example.com @::1 ; <<>> DiG 9.20.11-4-Debian <<>> AXFR example.com @::1 ;; global options: +cmd example.com. 1800 IN SOA ns1.example.com. hostmaster.example.com. 999 10800 10800 108000 1800 example.com. 10800 IN NS ns1.example.com. example.com. 1800 IN SOA ns1.example.com. hostmaster.example.com. 999 10800 10800 108000 1800 ;; Query time: 4 msec ;; SERVER: ::1#53(::1) (TCP) ;; WHEN: Wed Sep 03 20:40:31 BST 2025 ;; XFR size: 3 records (messages 3, bytes 264)
Sync
Update serial in SOA and then send notify to slave.
Update method 1
eg. with serial 1688651644
update records set content='ns1.example.com hostmaster.example.com 1688651644 10800 10800 108000 1800' where type='SOA' and domain_id=1;
Update method 2
pdnsutil increase-serial example.com
Notify
When the domain type is set to NATIVE or MASTER (not SLAVE) a notify can be sent manually.
pdns_control notify-host example.com X.X.X.X
NB If the domain type is MASTER a notify will be sent automatically by Power DNS but it may be delayed.

