PowerDNS is a free and open source DNS server written in C++ language that can be used to host domains using DNSSEC. It runs on most unix-based operating systems and uses databases like MariaDB, MySQL, PostgreSQL and SQLite to store its DNS entries. PowerDNS uses Packet Cache and Query Cache to cache backend queries. PowerDNS comes with a built-in web based tool: PowerDNS-Admin, which can be used to manage PowerDNS through web interface.
In this tutorial, we will explain how to install PowerDNS on an Ubuntu 20.04 cloud server.
Requirements
- A vps cloud server running on Ubuntu 20.04.
- A root password setup on your server.
Getting Started
First, it is recommended to update your server with the latest version. You can do it with the following command:
# apt-get update && apt-get upgrade -y
Once your system is updated, restart it to apply all the changes.
Install and Configure MariaDB
First, you will need to install MariaDB database in your server. You can install it by running the following command:
# apt-get install mariadb-server mariadb-client -y
Once the installation has been completed, you will need to create database and user for PowerDNS.
First, log in to MariaDB shell with the following command:
# mysql -u root -p
Provide your root password when prompt, then create a database and user for PowerDNS with the following command:
MariaDB [(none)]>CREATE DATABASE powerdns;
MariaDB [(none)]>GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'password';
Next, flush the privileges with the following command:
# MariaDB [(none)]>FLUSH PRIVILEGES;
Next, change the database to PowerDNS and create required tables with the following command:
# MariaDB [(none)]>USE powerdns;
MariaDB [powerdns]>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’;
MariaDB [powerdns]>CREATE UNIQUE INDEX name_index ON domains(name);
MariaDB [powerdns]>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’;
MariaDB [powerdns]>CREATE INDEX nametype_index ON records(name,type);
MariaDB [powerdns]>CREATE INDEX domain_id ON records(domain_id);
MariaDB [powerdns]>CREATE INDEX ordername ON records (ordername);
MariaDB [powerdns]>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’;
MariaDB [powerdns]>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’;
MariaDB [powerdns]>CREATE INDEX comments_name_type_idx ON comments (name, type);
MariaDB [powerdns]>CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);
MariaDB [powerdns]>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’;
MariaDB [powerdns]>CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);
MariaDB [powerdns]>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’;
MariaDB [powerdns]>CREATE INDEX domainidindex ON cryptokeys(domain_id);
MariaDB [powerdns]>CREATE TABLE tsigkeys ( id INT AUTO_INCREMENT, name VARCHAR(255), algorithm VARCHAR(50), secret VARCHAR(255), PRIMARY KEY (id)) Engine=InnoDB CHARACTER SET ‘latin1’;
MariaDB [powerdns]>CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
You can also check the created tables with the following command:
MariaDB [powerdns]> show tables;
+--------------------+
| Tables_in_powerdns |
+--------------------+
| comments |
| cryptokeys |
| domainmetadata |
| domains |
| records |
| supermasters |
| tsigkeys |
+--------------------+
7 rows in set (0.00 sec)
Install PowerDNS
First, you will need to disable systemd-resolve in order to PowerDNS work properly.
You can do it with the following command:
# systemctl disable systemd-resolved
# systemctl stop systemd-resolved
Next, remove the default resolv.conf file and create new one with the following command:
# rm /etc/resolv.conf
# echo "nameserver 8.8.8.8" > /etc/resolv.conf
Now, install PowerDNS with the following command:
# apt-get install pdns-server pdns-backend-mysql virtualenv -y
During the installation, you will be asked whether to configure the PowerDNS database with dbconfig-common. Select No and press Enter to continue the installation.
Next, you will need to configure PowerDNS to use MySQL. You can do it by editing PowerDNS configuration file:
# nano /etc/powerdns/pdns.d/pdns.local.gmysql.conf
Make the following changes:
launch+=gmysql
gmysql-host=localhost
gmysql-port=3306
gmysql-dbname=powerdns
gmysql-user=powerdns
gmysql-password=password
gmysql-dnssec=yes
Save and close the file. Then, restart PowerDNS service to apply the changes:
# systemctl restart pdns
You can also check the status of PowerDNS with the following command:
# systemctl status pdns
You should see the following output:
pdns.service - PowerDNS Authoritative Server
Loaded: loaded (/lib/systemd/system/pdns.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2019-06-24 15:29:08 UTC; 5s ago
Docs: man:pdns_server(1)
man:pdns_control(1)
https://doc.powerdns.com
Main PID: 8915 (pdns_server)
Tasks: 8 (limit: 1718)
CGroup: /system.slice/pdns.service
└─8915 /usr/sbin/pdns_server --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: TCPv6 server bound to [::]:53
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: PowerDNS Authoritative Server 4.1.1 (C) 2001-2017 PowerDNS.COM BV
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: Using 64-bits mode. Built using gcc 7.3.0.
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistr
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: Creating backend connection for TCP
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: [bindbackend] Parsing 0 domain(s), will report when done
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed
Jun 24 15:29:08 ubuntu2004 systemd[1]: Started PowerDNS Authoritative Server.
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: About to create 3 backend threads for UDP
Jun 24 15:29:08 ubuntu2004 pdns_server[8915]: Done launching threads, ready to distribute questions
Install PowerDNS-Admin
Next, you will need to install PowerDNS-Admin web interface to your server. You can manage domain, user, local DB, LDAP, PowerDNS service and much more with PowerDNS-Admin.
First, you will need to install some packages required for PowerDNS-Admin to your server. You can install all of them with the following command:
# apt-get install python3-dev libmysqlclient-dev python-mysqldb libsasl2-dev libffi-dev libldap2-dev libssl-dev libxml2-dev libxslt1-dev libxmlsec1-dev pkg-config -y
Next, you will also need to install yarn to your server.
First, download and add the GPG key with the following command:
# curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
Next, add the yarn repository with the following command:
# echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list
Next, update the repository and install yarn with the following command:
# apt-get update -y
# apt-get install yarn -y
Next, download the latest version of PowerDNS-Admin from the Git repository:
# git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git /opt/web/powerdns-admin
Next, create the virtual environment for PowerDNS-Admin with the following command:
# cd /opt/web/powerdns-admin
# virtualenv -p python3 flask
Next, activate the python3 environment and install all the required packages with the following command:
# . ./flask/bin/activate
# pip install -r requirements.txt
Next, you will need to rename config_template.py file and define your database in this file:
# mv config_template.py config.py
# nano config.py
Make the following changes:
SQLA_DB_USER = 'powerdns'
SQLA_DB_PASSWORD = 'password'
SQLA_DB_HOST = 'localhost'
SQLA_DB_NAME = 'powerdns'
#MySQL
SQLALCHEMY_DATABASE_URI = 'mysql://'+SQLA_DB_USER+':'+SQLA_DB_PASSWORD+'@'+SQLA_DB_HOST+'/'+SQLA_DB_NAME
SQLite
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db')
Save and close the file. Then, create the database schema file:
export FLASK_APP=app/__init__.py
flask db upgrade
flask db migrate -m "Init DB"
Next, generate the asset files using the yarn command as shown below:
# yarn install --pure-lockfile
# flask assets build
You should see the following output:
Building bundle: generated/login.js[2019-06-24 16:27:54,218] [INFO] | Building bundle: generated/login.js
Building bundle: generated/validation.js
[2019-06-24 16:27:54,848] [INFO] | Building bundle: generated/validation.js
Building bundle: generated/login.css
[2019-06-24 16:27:54,859] [INFO] | Building bundle: generated/login.css
Building bundle: generated/main.js
[2019-06-24 16:29:31,467] [INFO] | Building bundle: generated/main.js
Building bundle: generated/main.css
[2019-06-24 16:29:34,217] [INFO] | Building bundle: generated/main.css
Next, you can check your PowerDNS-Admin with the following command:
# ./run.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING
Do not use the development server in a production environment.Use a production WSGI server instead.
# * Debug mode: on # [2019-06-24 16:49:06,065] [INFO] | * Running on http://127.0.0.1:9191/ (Press CTRL+C to quit) # [2019-06-24 16:49:06,068] [INFO] | * Restarting with stat # [2019-06-24 16:49:19,104] [WARNING] | * Debugger is active! # [2019-06-24 16:49:19,107] [INFO] | * Debugger PIN: 193-133-562
Install and Configure Nginx
Next, you will need to install Nginx to access PowerDNS-Admin from web browser.
First, install Nginx with the following command:
# apt-get install nginx -y
Next, you will need to create an Nginx virtual host file for PowerDNS-Admin. You can do it with the following command:
# nano /etc/nginx/conf.d/powerdns-admin.conf
Add the following lines:
server {
listen *:80;
server_name example.com;
index index.html index.htm index.php;
root /opt/web/powerdns-admin;
access_log /var/log/nginx/powerdns.access.log combined;
error_log /var/log/nginx/powerdns.error.log;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_redirect off;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffers 32 4k;
proxy_buffer_size 8k;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_headers_hash_bucket_size 64;
location ~ ^/static/ {
include /etc/nginx/mime.types;
root /opt/web/powerdns-admin/app;
location ~* \.(jpg|jpeg|png|gif)$ {
expires 365d;
}
location ~* ^.+.(css|js)$ {
expires 7d;
}
}
location / {
proxy_pass http://unix:/opt/web/powerdns-admin/powerdns-admin.sock;
proxy_read_timeout 120;
proxy_connect_timeout 120;
proxy_redirect off;
}
}
Save and close the file, when you are finished. Then, restart Nginx service to apply all the changes:
# systemctl restart nginx
Create Systemd Service file for PowerDNS-Admin
Next, you will need to create a systemd service file for PowerDNS-Admin. So, you can start, stop, and manage PowerDNS-Admin service. You can do it with the following command:
# nano /etc/systemd/system/powerdns.service
Add the following lines:
[Unit]
Description=PowerDNS-Admin
After=network.target
[Service]
User=root
Group=root
WorkingDirectory=/opt/web/powerdns-admin
ExecStart=/opt/web/powerdns-admin/flask/bin/gunicorn --workers 2 --bind unix:/opt/web/powerdns-admin/powerdns-admin.sock app:app
[Install]
WantedBy=multi-user.target
Save and close the file, when you are finished. Then, start PowerDNS-Admin service and enable it to start on boot with the following command:
# systemctl daemon-reload
# systemctl start powerdns
# systemctl enable powerdns
Now, PowerDNS-Admin is installed and configured. You can open your web browser and the URL http://example.com. You will be redirected to the PowerDNS-Admin web interface.
Conclusion
Congratulations! You have successfully installed and configured PowerDNS and PowerDNS-Admin on Ubuntu 20.04 server. We hope you have now enough knowledge to host your domain and zone records using PowerDNS-Admin web interface.
Any questions? Don´t hesitate to contact us. We´ll be happy to help you out 🙂