This shows you how to configure the Generic MySQL backend. This backend
is called ‘gmysql’, and needs to be configured in pdns.conf
. Add the
following lines, adjusted for your local setup (specifically, you may
not want to use the ‘root’ user):
launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=root
gmysql-dbname=pdns
gmysql-password=mysecretpassword
Remove any earlier launch statements and other configuration statements for backends.
Warning
Make sure that you can actually resolve the hostname of your database without accessing the database! It is advised to supply an IP address here to prevent chicken/egg problems!
Now start PowerDNS in the foreground:
# /usr/sbin/pdns_server --daemon=no --guardian=no --loglevel=9
(...)
Dec 30 13:40:09 About to create 3 backend threads for UDP
Dec 30 13:40:09 gmysql Connection failed: Unable to connect to database: Access denied for user 'hubert'@'localhost' to database 'pdns-non-existant'
Dec 30 13:40:09 Caught an exception instantiating a backend: Unable to launch gmysql connection: Unable to connect to database: Access denied for user 'hubert'@'localhost' to database 'pdns-non-existant'
Dec 30 13:40:09 Cleaning up
Dec 30 13:40:10 Done launching threads, ready to distribute questions
This is as to be expected - we did not yet add anything to MySQL for PowerDNS to read from. At this point you may also see other errors which indicate that PowerDNS either could not find your MySQL server or was unable to connect to it. Fix these before proceeding.
General MySQL knowledge is assumed in this chapter, please do not interpret these commands as DBA advice!
Connect to MySQL as a user with sufficient privileges and issue the following commands:
CREATE TABLE domains (
id INT AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
master VARCHAR(128) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT UNSIGNED DEFAULT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE TABLE records (
id BIGINT AUTO_INCREMENT,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(10) DEFAULT NULL,
content VARCHAR(64000) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
change_date INT DEFAULT NULL,
disabled TINYINT(1) DEFAULT 0,
ordername VARCHAR(255) BINARY DEFAULT NULL,
auth TINYINT(1) DEFAULT 1,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX ordername ON records (ordername);
CREATE TABLE supermasters (
ip VARCHAR(64) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (ip, nameserver)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE TABLE comments (
id INT AUTO_INCREMENT,
domain_id INT NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(10) NOT NULL,
modified_at INT NOT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
comment TEXT CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);
CREATE TABLE domainmetadata (
id INT AUTO_INCREMENT,
domain_id INT NOT NULL,
kind VARCHAR(32),
content TEXT,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);
CREATE TABLE cryptokeys (
id INT AUTO_INCREMENT,
domain_id INT NOT NULL,
flags INT NOT NULL,
active BOOL,
content TEXT,
PRIMARY KEY(id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX domainidindex ON cryptokeys(domain_id);
CREATE TABLE tsigkeys (
id INT AUTO_INCREMENT,
name VARCHAR(255),
algorithm VARCHAR(50),
secret VARCHAR(255),
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
Now we have a database and an empty table. PowerDNS should now be able to launch in monitor mode and display no errors:
# /usr/sbin/pdns_server --daemon=no --guardian=no --loglevel=9
(...)
15:31:30 PowerDNS 1.99.0 (Mar 12 2002, 15:00:28) starting up
15:31:30 About to create 3 backend threads
15:39:55 [gMySQLbackend] MySQL connection succeeded
15:39:55 [gMySQLbackend] MySQL connection succeeded
15:39:55 [gMySQLbackend] MySQL connection succeeded
In a different shell, a sample query sent to the server should now return quickly without data:
$ dig +short www.example.com @127.0.0.1
$
Warning
When debugging DNS problems, don’t use host
. Please use
dig
or drill
.
And indeed, the output in the first terminal now shows:
Mar 01 16:04:42 Remote 127.0.0.1 wants 'www.example.com|A', do = 0, bufsize = 1680: packetcache MISS
Now we need to add some records to our database (in a separate shell):
# mysql pdnstest
mysql> INSERT INTO domains (name, type) values ('example.com', 'NATIVE');
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','localhost admin.example.com 1 10380 3600 604800 3600','SOA',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','dns-us1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','dns-eu1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'www.example.com','192.0.2.10','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'mail.example.com','192.0.2.12','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'localhost.example.com','127.0.0.1','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','mail.example.com','MX',120,25);
Warning
Host names and the MNAME of a SOA records are NEVER terminated with a ‘.’ in PowerDNS storage! If a trailing ‘.’ is present it will inevitably cause problems, problems that may be hard to debug.
If we now requery our database, www.example.com
should be present:
$ dig +short www.example.com @127.0.0.1
192.0.2.10
$ dig +short example.com MX @127.0.0.1
25 mail.example.com
To confirm what happened, check the statistics:
$ /usr/sbin/pdns_control SHOW \*
corrupt-packets=0,latency=0,packetcache-hit=2,packetcache-miss=5,packetcache-size=0,
qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,
timedout-packets=0,udp-answers=7,udp-queries=7,
%
The actual numbers will vary somewhat. Now hit CTRL+C in the shell where PowerDNS runs, start PowerDNS as a regular daemon, and check launch status:
On SysV systems:
# /etc/init.d/pdns start
pdns: started
# /etc/init.d/pdns status
pdns: 8239: Child running
# /etc/init.d/pdns dump
pdns: corrupt-packets=0,latency=0,packetcache-hit=0,packetcache-miss=0,
packetcache-size=0,qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,
tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,
On systemd systems:
# systemctl start pdns.service
# systemctl status pdns.service
* pdns.service - PowerDNS Authoritative Server
Loaded: loaded (/lib/systemd/system/pdns.service; enabled)
Active: active (running) since Tue 2017-01-17 15:59:28 UTC; 1 months 12 days ago
Docs: man:pdns_server(1)
man:pdns_control(1)
https://doc.powerdns.com
Main PID: 24636 (pdns_server)
CGroup: /system.slice/pdns.service
`-24636 /usr/sbin/pdns_server --guardian=no --daemon=no --disable-syslog --write-pid=no
(...)
# /usr/sbin/pdns_control SHOW \*
corrupt-packets=0,latency=0,packetcache-hit=2,packetcache-miss=5,packetcache-size=0,
qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,
timedout-packets=0,udp-answers=7,udp-queries=7,
You now have a working database driven nameserver! To convert other zones already present, see the migration guide.
Most problems involve PowerDNS not being able to connect to the database.
Your MySQL installation is probably defaulting to another location for
its socket. Can be resolved by figuring out this location (often
/var/run/mysqld.sock
), and specifying it in the configuration file
with the gmysql-socket parameter.
Another solution is to not connect to the socket, but to 127.0.0.1,
which can be achieved by specifying gmysql-host=127.0.0.1
.
These errors are generic MySQL errors. Solve them by trying to connect
to your MySQL database with the MySQL console utility mysql
with the
parameters specified to PowerDNS. Consult the MySQL documentation.
At this point some things may have gone wrong. Typical errors include:
This means that another nameserver is listening on port 53 already. You
can resolve this problem by determining if it is safe to shutdown the
nameserver already present, and doing so. If uncertain, it is also
possible to run PowerDNS on another port. To do so, add
local-port=5300 to pdns.conf
, and
try again. This however implies that you can only test your nameserver
as clients expect the nameserver to live on port 53.
You must be superuser in order to be able to bind to port 53. If this is
not a possibility, it is also possible to run PowerDNS on another port.
To do so, add local-port=5300 to
pdns.conf
, and try again. This however implies that you can only
test your nameserver as clients expect the nameserver to live on port
53.
PowerDNS did not find the launch=bind
instruction in pdns.conf.
If you have multiple IP addresses on the internet on one machine, UNIX often sends out answers over another interface than which the packet came in on. In such cases, use local-address to bind to specific IP addresses, which can be comma separated. The second error comes from remotes disregarding answers to questions it didn’t ask to that IP address and sending back ICMP errors.