Learn how to – Configure PowerDNS and PowerDNS Admin on Rocky Linux 9|8.
In this guide today, we will cover how to configure PowerDNS and PowerDNS Admin on Rocky Linux 9|8. But before we dive into the crux of the matter, we need to know what this tool is all about.
DNS is an acronym for Domain Name System. This is an internet service used to resolve an IP addresses to a domain names and vice-versa. This reduces the complexity involved in memorizing several IP addresses associated with web pages. Normally, human beings access sites over the internet using domain names such as google.com, ownyourlife.com.ng e.t.c. These domain names are tied to these IP addresses. It is the work of the DNS to translate the addresses to allow the browsers to load the pages. Today there are several DNS solutions in the market. They include BIND DNS, Knot DNS, NSD, MaraDNS, YADIFA, PowerDNS e.t.c
PowerDNS is a tool that provides both Authoritative Server and Recursor DNS products. Authoritative DNS responds to all queries about the domains it knows and ignores those it doesn’t know. The Recursor DNS on the other side has no knowledge about any domain and relies on the authoritative DNS to provide answers to queries directed to it. The two product are offered separately by PowerDNS but are often be combined to work seamlessly.
PowerDNS was first developed as a commercial product in 1999 then later became open-source in 2002. The popularity of this tool has grown immensely due to the following features:
- High domain resolution performance.
- Very improved security features.
- Supports several backends ranging from simple zonefiles, relational databases all the way to load balancing/failover algorithms.
- It provides a lot of statistics during its operation which helps to determine the scalability of an installation and also spotting problems.
The PowerDNS Admin provied the admin web interface from which you can create and manage the PowerDNS DNS zones.
It offers a lot of amazing features. Some of them are:
- Multiple domain management
- Offers limited API for manipulating zones and records
- User management
- Provides a domain template
- Supports Google/Github/Azure/OpenID OAuth
- Dashboard and pdns service statistics
- Supports DynDNS 2 protocol
- Support Local DB/SAML/LDAP/Active Directory user authentication
- Supports a Two-factor authentication (TOTP) protocol
Now let’s plunge in and enjoy the awesomeness of this product.
Getting Started
In this guide, we will install and configure:
- PowerDNS and PowerDNS Admin
- MariaDB database server
We also need to enable the EPEL repository to provide other required packages:
sudo yum install epel-release
Set SELinux in permissive mode:
sudo setenforce 0 && sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
cat /etc/selinux/config | grep SELINUX=
#1. Install and Configure MariaDB on Rocky Linux 9|8
PowerDNS supports several database backends that include MySQL, PostgreSQL, Oracle e.t.c. In this guide we will use MariaDB as the backend storage.
Install MariaDB on Rocky Linux 9|8 with the command:
sudo dnf install mariadb-server mariadb
Start and enable the service:
sudo systemctl enable --now mariadb
Harden the instance as shown
$ sudo mysql_secure_installation
....
Enter current password for root (enter for none): Just press Enter
......
Switch to unix_socket authentication [Y/n] Y
.....
Change the root password? [Y/n] Y
New password: New-root-password
Re-enter new password: Re-enter New-root-password
....
Remove anonymous users? [Y/n] Y
....
Disallow root login remotely? [Y/n] Y
.....
Remove test database and access to it? [Y/n] Y
......
Reload privilege tables now? [Y/n] Y
...
Thanks for using MariaDB!
Login to the shell:
sudo mysql -u root -p
Create a database for PowerDNS
CREATE DATABASE powerdns;
GRANT ALL ON powerdns.* TO 'powerdns_user'@'%' IDENTIFIED BY 'Strongpassword';
FLUSH PRIVILEGES;
Remeber to use a password with no special characters, because it can cause an error “Access denied for user ‘powerdns_user’@’localhost’ (using password: YES)“ on PowerDNS.
Proceed and create the PowerDNS tables:
use powerdns;
Use the below commands to add tables:
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 DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL,
PRIMARY KEY (id)
) Engine=InnoDB;
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;
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername);
CREATE TABLE supermasters (
ip VARCHAR(64) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) NOT NULL,
PRIMARY KEY (ip, nameserver)
) Engine=InnoDB;
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) NOT NULL,
comment VARCHAR(64000) NOT NULL,
PRIMARY KEY (id)
) Engine=InnoDB;
CREATE INDEX comments_domain_id_idx ON comments (domain_id);
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;
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;
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;
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
Verify if the tables exist:
MariaDB [powerdns]> show tables;
+--------------------+
| Tables_in_powerdns |
+--------------------+
| comments |
| cryptokeys |
| domainmetadata |
| domains |
| records |
| supermasters |
| tsigkeys |
+--------------------+
7 rows in set (0.000 sec)
MariaDB [powerdns]> quit;
#2. Install PowerDNS on Rocky Linux 9|8
on Rocky Linux 8, you need to disable the systemd-resolved service running on port 53 because this is the same port to be used by PowerDNS.
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
Delete the symbolic link for the file:
$ ls -lh /etc/resolv.conf
-rw-r--r--. 1 root root 55 Aug 24 06:46 /etc/resolv.conf
$ sudo unlink /etc/resolv.conf
Now create a new symbolic link:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
You also need to stop and disable dnsmasq
:
sudo systemctl disable dnsmasq
sudo systemctl stop dnsmasq
Restart the network manager:
sudo service NetworkManager restart
Kill all the dnsmasq services:
sudo killall dnsmasq
Since PowerDNS exists in the EPEL repositories, we can install it with the command:
sudo dnf -y install pdns pdns-backend-mysql bind-utils
#3. Configure the PowerDNS Database
SInce we already have a database created on MariaDB, we will simply edit configuration file to allow PowerDNS to use the database:
sudo vim /etc/pdns/pdns.conf
Make the below changes to the file, ensure launch=bind is commented out.
# launch=bind
launch=gmysql
# gmysql parameters
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=powerdns
gmysql-user=powerdns_user
gmysql-password=Strongpassword
Save the changes, and verify the connection to the database:
sudo systemctl stop pdns.service
sudo pdns_server --daemon=no --guardian=no --loglevel=9
Sample Output:
Start and enable PowerDNS:
sudo killall -9 pdns_server
sudo systemctl start pdns
sudo systemctl enable pdns
Verify if the service is running:
$ sudo ss -alnp4 | grep pdns
udp UNCONN 0 0 0.0.0.0:53 0.0.0.0:* users:(("pdns_server",pid=33244,fd=5))
tcp LISTEN 0 128 0.0.0.0:53 0.0.0.0:* users:(("pdns_server",pid=33244,fd=7))
Allow the DNS service through the firewall:
sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload
Also verify if PowerDNS is responding to requests:
$ dig @127.0.0.1
; <<>> DiG 9.16.23-RH <<>> @127.0.0.1
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 18968
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;. IN NS
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Aug 24 13:15:24 CEST 2022
;; MSG SIZE rcvd: 28
#4. Install PowerDNS Admin on Rocky Linux 9|8
Now we can install PowerDNS Admin, a web admin interface to easily manage the PowerDNS server. Bu now, we will install the required build tools. Add the REMI repo and enable PowerTools
##On Rocky Linux 8
sudo dnf -y install http://rpms.remirepo.net/enterprise/remi-release-8.rpm
sudo dnf config-manager --set-enabled powertools
##On Rocky Linux 9
sudo dnf -y install http://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf config-manager --set-enabled crb
Install the Python development and other packages.
sudo yum install python3-devel gcc python3-pip git mariadb-connector-c-devel xmlsec1 openldap-devel xmlsec1-openssl-devel postgresql-devel libxslt-devel libffi-devel cyrus-sasl-devel libtool-ltdl-devel
Uisng PIP, install Flask and virtualenv
sudo pip3 install virtualenv flask
Also install Node.js on Rocky Linux 9|8
curl -sL https://rpm.nodesource.com/setup_18.x | sudo -E bash -
sudo yum install -y nodejs
Also install the Yarn package:
curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
sudo yum install yarn
Now clone the PowerDNS admin source code to /var/www/html/pdns
sudo su -
git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git /var/www/html/pdns
Switch to the directory and create the virtual environment:
cd /var/www/html/pdns/
virtualenv -p python3 flask
Active the virtual environment and install the required packages.
source ./flask/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
Once complete, deactivate the environment:
deactivate
Edit the below file to allow PowerDNS admin to connect to the database;
vim /var/www/html/pdns/powerdnsadmin/default_config.py
Make the below adjustments:
### DATABASE CONFIG
SQLA_DB_USER = 'powerdns_user'
SQLA_DB_PASSWORD = 'Strongpassword'
SQLA_DB_HOST = '127.0.0.1'
SQLA_DB_NAME = 'powerdns'
SQLALCHEMY_TRACK_MODIFICATIONS = True
Create a database schema:
cd /var/www/html/pdns/
source ./flask/bin/activate
export FLASK_APP=powerdnsadmin/__init__.py
flask db upgrade
Sample Output:
INFO [alembic.runtime.migration] Context impl MySQLImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 787bdba9e147, Init DB
INFO [alembic.runtime.migration] Running upgrade 787bdba9e147 -> 59729e468045, Add view column to setting table
INFO [alembic.runtime.migration] Running upgrade 59729e468045 -> 1274ed462010, Change setting.value data type
INFO [alembic.runtime.migration] Running upgrade 1274ed462010 -> 4a666113c7bb, Adding Operator Role
INFO [alembic.runtime.migration] Running upgrade 4a666113c7bb -> 31a4ed468b18, Remove all setting in the DB
INFO [alembic.runtime.migration] Running upgrade 31a4ed468b18 -> 654298797277, Upgrade DB Schema
INFO [alembic.runtime.migration] Running upgrade 654298797277 -> 0fb6d23a4863, Remove user avatar
INFO [alembic.runtime.migration] Running upgrade 0fb6d23a4863 -> 856bb94b7040, Add comment column in domain template record table
INFO [alembic.runtime.migration] Running upgrade 856bb94b7040 -> b0fea72a3f20, Update domain serial columns type
INFO [alembic.runtime.migration] Running upgrade b0fea72a3f20 -> 3f76448bb6de, Add user.confirmed column
INFO [alembic.runtime.migration] Running upgrade 3f76448bb6de -> 0d3d93f1c2e0, Add domain_id to history table
INFO [alembic.runtime.migration] Running upgrade 0d3d93f1c2e0 -> 0967658d9c0d, add apikey account mapping table
INFO [alembic.runtime.migration] Running upgrade 0967658d9c0d -> fbc7cf864b24, update history detail quotes
INFO [alembic.runtime.migration] Running upgrade fbc7cf864b24 -> 6ea7dc05f496, Fix typo in history detail
Now generate the asset files with Yarn:
yarn install --pure-lockfile
flask assets build
Deactivate the environment:
deactivate
#5. Enable PowerDNS API access on Rocky Linux 9|8
To enable the PowerDNS API access, we need to edit the below file;
sudo vim /etc/pdns/pdns.conf
Make the below changes to the file:
# api Enable/disable the REST API (including HTTP listener)
#
# api=no
api=yes
#################################
# api-key Static pre-shared authentication key for access to the REST API
#
# api-key=
api-key=3ce1af6c-981d-4190-a559-1e691d89b90e #You can generate one from https://codepen.io/corenominal/pen/rxOmMJ
Save the file and restart the service:
sudo systemctl restart pdns
#6. Install and Configure Nginx for Powerdns
To be able to load the PowerDNS web interface, we need to install and configure Nginx.
sudo yum install nginx
Once installed, create a virtualhost file for PowerDNS admin.
vim /etc/nginx/conf.d/powerdns-admin.conf
ADd the below lines and make changes where required:
server {
listen *:80;
server_name pdnsadmin.ownyourlife.com.ng;
index index.html index.htm index.php;
root /var/www/html/pdns;
access_log /var/log/nginx/pdnsadmin_access.log combined;
error_log /var/log/nginx/pdnsadmin_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 /var/www/html/pdns/powerdnsadmin;
location ~* .(jpg|jpeg|png|gif)$ {
expires 365d;
}
location ~* ^.+.(css|js)$ {
expires 7d;
}
}
location / {
proxy_pass http://unix:/run/pdnsadmin/socket;
proxy_read_timeout 120;
proxy_connect_timeout 120;
proxy_redirect off;
}
}
Set the correct ownership for the path:
chown -R nginx: /var/www/html/pdns
Restart Nginx:
systemctl restart nginx
Allow the service through the firewall:
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload
#7. Create a Service file for PowerDNS Admin
To be able to manage the PowerDNS Admin service, we need to create a systemd service file;
vim /etc/systemd/system/pdnsadmin.service
The file will contain the below lines:
[Unit]
Description=PowerDNS-Admin
Requires=pdnsadmin.socket
After=network.target
[Service]
PIDFile=/run/pdnsadmin/pid
User=pdns
Group=pdns
WorkingDirectory=/var/www/html/pdns
ExecStart=/var/www/html/pdns/flask/bin/gunicorn --pid /run/pdnsadmin/pid --bind unix:/run/pdnsadmin/socket 'powerdnsadmin:create_app()'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Create a socket file for PowerDNS admin;
sudo vim /etc/systemd/system/pdnsadmin.socket
Add the below lines to the file;
[Unit]
Description=PowerDNS-Admin socket
[Socket]
ListenStream=/run/pdnsadmin/socket
[Install]
WantedBy=sockets.target
Finally, create an environment file
mkdir /run/pdnsadmin/
echo "d /run/pdnsadmin 0755 pdns pdns -" >> /etc/tmpfiles.d/pdnsadmin.conf
Set the correct ownership of the files:
chown -R pdns: /run/pdnsadmin/
chown -R pdns: /var/www/html/pdns/powerdnsadmin/
Reload the system deamon;
systemctl daemon-reload
Start and enable PowerDNS Admin on Rocky Linux 9|8
systemctl enable --now pdnsadmin.service pdnsadmin.socket
Verify if the service is running:
$ systemctl status pdnsadmin.service pdnsadmin.socket
pdnsadmin.service - PowerDNS-Admin
Loaded: loaded (/etc/systemd/system/pdnsadmin.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2022-08-24 14:42:36 CEST; 9s ago
TriggeredBy: ● pdnsadmin.socket
Main PID: 92303 (gunicorn)
Tasks: 2 (limit: 23441)
Memory: 69.4M
CPU: 690ms
CGroup: /system.slice/pdnsadmin.service
├─92303 /var/www/html/pdns/flask/bin/python /var/www/html/pdns/flask/bin/gunicorn --pid /run/pdnsadmin/pid --bind unix:/run/pd>
└─92304 /var/www/html/pdns/flask/bin/python /var/www/html/pdns/flask/bin/gunicorn --pid /run/pdnsadmin/pid --bind unix:/run/pd>
Aug 24 14:42:36 localhost.localdomain systemd[1]: Started PowerDNS-Admin.
Aug 24 14:42:36 localhost.localdomain gunicorn[92303]: [2022-08-24 14:42:36 +0200] [92303] [INFO] Starting gunicorn 20.0.4
Aug 24 14:42:36 localhost.localdomain gunicorn[92303]: [2022-08-24 14:42:36 +0200] [92303] [INFO] Listening at: unix:/run/pdnsadmin/socket >
Aug 24 14:42:36 localhost.localdomain gunicorn[92303]: [2022-08-24 14:42:36 +0200] [92303] [INFO] Using worker: sync
Aug 24 14:42:36 localhost.localdomain gunicorn[92304]: [2022-08-24 14:42:36 +0200] [92304] [INFO] Booting worker with pid: 92304
● pdnsadmin.socket - PowerDNS-Admin socket
Loaded: loaded (/etc/systemd/system/pdnsadmin.socket; enabled; vendor preset: disabled)
Active: active (running) since Wed 2022-08-24 14:42:36 CEST; 9s ago
Until: Wed 2022-08-24 14:42:36 CEST; 9s ago
Triggers: ● pdnsadmin.service
Listen: /run/pdnsadmin/socket (Stream)
CGroup: /system.slice/pdnsadmin.socket
Aug 24 14:42:36 localhost.localdomain systemd[1]: Listening on PowerDNS-Admin socket.
#8. Access the PowerDNS Admin UI
Once the above configurations have been made, you can access the PowerDNS web UI using the URL http://domain_name or http://IP_address.
Create a user account.
Once created, login to PowerDNS Admin using the user credentials.
You will see the dashboard. Now connect to the PowerDNS server by providing the API Key defined in the PowerDNS config file(/etc/powerdns/pdns.conf) and URL (http://127.0.0.1:8081) as shown:
Once provided, click update and the error will disappear. You can now manage the PowerDNS server.
To create a new domain, click on +New Domain tab
Provide the domain name, select the template to be used from the templates list, and submit. The added domain will appear as shown;
Records can now be added to the domain by clicking on it and providing the record name. Once added, save and apply the changes:
That was a brief demonstration on how to get started with PowerDNS and PowerDNS admin. I hope this was significant to you. There are many other configurations you can make from the PowerDNS admin UI such as editing the domain templates, removing domains, managing user accounts e.t.c. I hope this was significant to you.
See more:
- Bind vs dnsmasq vs PowerDNS vs Unbound
- Running PowerDNS and PowerDNS Admin in Docker Containers
- Install PowerDNS and PowerDNS Admin on Debian
Leave a Reply
You must be logged in to post a comment.