Authoritive Nameservers
I have the following going for me:
All are running Ubuntu 18.10 (cosmic) with the following software from the default repositories:
- PowerDNS 4.1 Authoritive Nameserver
- MariaDB Server 10.3
Using a SQL-backend makes us able to enable the HTTP API, which opens up a whole new world of managing your domains.
However, I will be mainly managing and editing zones with pdnsutil
. You should really familiarise yourself with it, as it's really powerful and your one-stop tool for everything.
Installation of software (all nodes)
First, you should install the database-server we're going to use.
MariaDB/MySQL-server
Do not use SQLite for this! I repeat: Do NOT use SQLite for this. It often causes problems on production systems!
MariaDB 10.1 and higher also come with Galera Cluster integrated. You should, however, not use it if you don't have an odd amount of nodes of at least 3, set up in specific ways, etc. Additionally, if you're having a world-wide cluster of them like me, latency will already not be great.. and needing a VPN (suggestion: tinc
), will add even more latency. I've used it in the past and it worked, but it had a lot of caveats/problems. You're better off not using it.
MariaDB is a drop-in replacement for MySQL, and with the way MySQL is going, it's being ditched by other distributions as well (like Debian).
You can also install MySQL here, it won't change anything for the rest of the article here. You should set a password for the (MySQL-)root user here when asked:
apt install mariadb-server
Now, start by generating a password:
< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;
Paste it somewhere in a text file or something for now, you'll need it a few times later.
Open a privileged MySQL-prompt (this file contains credentials used by Ubuntu's system scripts, for easy and uniform access):
mysql --defaults-extra-file=/etc/mysql/debian.cnf
Set up the PowerDNS-account in MySQL with it:
GRANT ALL PRIVILEGES ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'password_you_created_earlier';
CREATE DATABASE powerdns;
USE powerdns;
Next, fill the database with the proper tables as explained on https://doc.powerdns.com/authoritative/backends/generic-mysql.html (recommended). If you're in a hurry, and starting with a fresh database, you can use my local copy (powerdns.sql) (fastest):
wget -O- https://finalx.nl/powerdns.sql | mysql --defaults-extra-file=/etc/mysql/debian.cnf powerdns
Or, alternatively copy/paste from here:
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);
ALTER TABLE records ADD CONSTRAINT `records_domain_id_ibfk` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE comments ADD CONSTRAINT `comments_domain_id_ibfk` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE domainmetadata ADD CONSTRAINT `domainmetadata_domain_id_ibfk` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE cryptokeys ADD CONSTRAINT `cryptokeys_domain_id_ibfk` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
PowerDNS 4.1 Authoritive Nameserver
Next, install PowerDNS and its MySQL-backend:
apt install pdns-server pdns-backend-mysql
The initial configuration for Ubuntu packages is located in /etc/powerdns. We will not be using the BIND-backend, and we shouldn't be touching /etc/powerdns/pdns.conf. Put your own configuration in /etc/powerdns/pdns.d/ instead. They give us some example configuration files by default, so remove them: Configuration
rm /etc/powerdns/pdns.d/*
Create a new configuration-file (/etc/powerdns/pdns.d/pdns.local.conf
) on each node, containing your MySQL-credentials for your PowerDNS-database:
launch=gmysql
gmysql-socket=/var/run/mysqld/mysqld.sock
gmysql-dbname=powerdns
gmysql-user=powerdns
gmysql-group=client
gmysql-password=<password_you_created_earlier>
gmysql-dnssec=yes
gmysql-innodb-read-committed=yes
gmysql-timeout=10
You should obviously replace <password_you_created_earlier>
with the actual password that you created earlier.
We will be expanding this configuration-file in the next article(s), but for now, we're done.
Please note that we are not using replication here. Each slave is stand-alone in cases of outage and to keep complexity low.
Further configuration
Configuration of the nodes is split up in different articles. Check out the following articles: