PowerDNS is a free and open-source DNS server developed in C++, which allows you to host domains with support for DNSSEC. It runs on most Unix-based operating systems and can store its DNS records in databases such as MariaDB, MySQL, PostgreSQL and SQLite.
Additionally, it includes packet and query caching mechanisms to optimize name resolution performance. For management, it provides a web tool called PowerDNS-Admin, offering an intuitive interface to centrally manage the server.
In this tutorial, you will learn how to install PowerDNS and PowerDNS-Admin on a cloud server running Ubuntu 24.04.
Prerequisites
- A cloud VPS server with Ubuntu 24.04 installed.
- Access to the server with the root user or a user with sudo privileges.
Getting Started
First, we recommend updating your cloud server packages to the latest version. You can do this with the following command:
# apt update && apt upgrade -y
Once your system is updated, reboot it to apply all changes.
Install and Configure MySQL/MariaDB
First, you need to install the MySQL/MariaDB database on your server. You can do this by running the following command:
# apt install pdns-backend-mysql mariadb-server -y
Once the installation is complete, you need to create the database and user for PowerDNS.
First, log in to the MariaDB shell with the following command:
# mariadb -u root
Enter your root password when prompted, then create a database and user for PowerDNS with:
MariaDB [(none)]>CREATE DATABASE powerdns;
MariaDB [(none)]>GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'password';
Next, flush privileges with the following command:
MariaDB [(none)]>FLUSH PRIVILEGES; EXIT;
Then, use the pdns SQL file to create the necessary tables with:
# mariadb -u root powerdns < /usr/share/pdns-backend-mysql/schema/schema.mysql.sql
Install PowerDNS
First, you need to disable systemd-resolved so that PowerDNS works correctly.
You can do this with:
# systemctl disable systemd-resolved && systemctl stop systemd-resolved
Next, reset the default resolv.conf file and create a new one with:
# echo "nameserver 8.8.8.8" > /etc/resolv.conf
# echo "nameserver 8.8.4.4" >> /etc/resolv.conf
Now, install PowerDNS with:
# apt-get install pdns-server virtualenv -y
During installation, you will be asked if you want to configure the PowerDNS database with dbconfig-common. Select ‘No’ and press ‘Enter’ to continue with the installation.
Next, configure PowerDNS to use MySQL by editing the 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 the PowerDNS service to apply the changes:
# systemctl restart pdns
You can also check the status of PowerDNS with:
# systemctl status pdns
You should see output similar to:
● pdns.service - PowerDNS Authoritative Server
Loaded: loaded (/usr/lib/systemd/system/pdns.service; enabled; preset: enabled)
Active: active (running) since Wed 2025-09-17 12:52:42 CEST; 11s ago
Docs: man:pdns_server(1)
man:pdns_control(1)
https://doc.powerdns.com
Main PID: 24867 (pdns_server)
Tasks: 8 (limit: 9436)
Memory: 46.5M (peak: 46.9M)
CPU: 92ms
CGroup: /system.slice/pdns.service
└─24867 /usr/sbin/pdns_server --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
Sep 17 11:44:54 powerdns pdns_server[18354]: TCP server bound to [::]:53
Sep 17 11:44:54 powerdns pdns_server[18354]: PowerDNS Authoritative Server 4.8.3 (C) 2001-2022 Powe
Sep 17 11:44:54 powerdns pdns_server[18354]: Using 64-bits mode. Built using gcc 13.2.0.
Sep 17 11:44:54 powerdns pdns_server[18354]: PowerDNS comes with ABSOLUTELY NO WARRANTY. This is fr
Sep 17 11:44:54 powerdns pdns_server[18354]: [bindbackend] Parsing 0 domain(s), will report when do
Sep 17 11:44:54 powerdns pdns_server[18354]: [bindbackend] Done parsing domains, 0 rejected, 0 new,
Sep 17 11:44:54 powerdns pdns_server[18354]: Creating backend connection for TCP
Sep 17 11:44:54 powerdns pdns_server[18354]: About to create 3 backend threads for UDP
Sep 17 11:44:54 powerdns systemd[1]: Started pdns.service - PowerDNS Authoritative Server.
Sep 17 11:44:54 powerdns pdns_server[18354]: Done launching threads, ready to distribute questionsInstall PowerDNS-Admin
Next, you need to install the PowerDNS-Admin web interface on your server. With PowerDNS-Admin, you can manage domains, users, local databases, LDAP, the PowerDNS service, and more.
First, install the necessary packages for PowerDNS-Admin on your server with:
# apt install python3-dev python3-mysqldb python3-certbot-nginx libpq-dev gcc libmysqlclient-dev libsasl2-dev libffi-dev libldap2-dev libssl-dev libxml2-dev libxslt1-dev libxmlsec1-dev pkg-config -y
Next, you also need to install Yarn on your server.
First, download and add the GPG key with:
# curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarnpkg-archive-keyring.gpg > /dev/null
Then, add the Yarn repository:
# echo "deb [signed-by=/usr/share/keyrings/yarnpkg-archive-keyring.gpg] https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
Update the repository and install Yarn with:
# apt update && apt install yarn nodejs -y && yarn --version
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
Create the virtual environment for PowerDNS-Admin:
# cd /opt/web/powerdns-admin && virtualenv -p python3 flask && pip3 install --upgrade setuptools
Activate the Python3 environment and install all required packages:
# . ./flask/bin/activate && pip3 install -r requirements.txt
Edit default_config.py to define your database:
# nano powerdnsadmin/default_config.py
Add the following lines:
SQLA_DB_USER = 'powerdns' SQLA_DB_PASSWORD = 'password' SQLA_DB_HOST = '127.0.0.1' SQLA_DB_NAME = 'powerdns' SQLALCHEMY_TRACK_MODIFICATIONS = True
Save and close the file. Then, create the database schema:
# export FLASK_APP=powerdnsadmin/__init__.py && flask db upgrade
Generate the asset files using Yarn:
# yarn install --pure-lockfile && flask assets build
You should see output like:
Building bundle: generated/login.js [2025-09-17 12:18:27,629] [script.py:167] INFO - Building bundle: generated/login.js Building bundle: generated/validation.js [2025-09-17 12:18:27,643] [script.py:167] INFO - Building bundle: generated/validation.js Building bundle: generated/login.css [2025-09-17 12:18:27,645] [script.py:167] INFO - Building bundle: generated/login.css Building bundle: generated/main.js [2025-09-17 12:18:27,695] [script.py:167] INFO - Building bundle: generated/main.js Building bundle: generated/main.css [2025-09-17 12:18:27,768] [script.py:167] INFO - Building bundle: generated/main.css
You can test PowerDNS-Admin with:
# ./run.py
Warning
Do not use the development server in a production environment. Use a production WSGI server instead.
* Serving Flask app 'powerdnsadmin' * Debug mode: on [2025-09-17 12:18:46,655] [_internal.py:187] INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:9191 * Running on http://161.22.44.39:9191 [2025-09-17 12:18:46,655] [_internal.py:187] INFO - Press CTRL+C to quit [2025-09-17 12:18:46,656] [_internal.py:187] INFO - * Restarting with stat [2025-09-17 12:18:47,354] [_internal.py:187] WARNING - * Debugger is active! [2025-09-17 12:18:47,358] [_internal.py:187] INFO - * Debugger PIN: 863-469-169
First, install NGINX:
# apt install nginx -y
Next, create an Nginx virtual host file for PowerDNS-Admin:
# nano /etc/nginx/conf.d/powerdns-admin.conf
Add the following lines:
server {
listen *:80; server_name powerdns.example.com; # Change to your domain
access_log /var/log/nginx/powerdns-admin.access.log;
error_log /var/log/nginx/powerdns-admin.error.log;
location / {
proxy_pass http://127.0.0.1:8000;
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_set_header X-Forwarded-Proto $scheme;
}
location /static/ {
alias /opt/web/powerdns-admin/powerdnsadmin/static/;
access_log off;
}
}Save and close the file. Then restart NGINX to apply changes:
# systemctl restart nginx
Next, create a systemd service file for PowerDNS-Admin so you can start, stop, and manage it:
# 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 -w 4 -b 127.0.0.1:8000 "powerdnsadmin:create_app()" [Install] WantedBy=multi-user.target
Save and close the file. Then start and enable the PowerDNS-Admin service:
# systemctl daemon-reload && systemctl enable powerdns && systemctl start powerdns
Finally, use Certbot to obtain and configure the SSL certificate for HTTPS:
# certbot --nginx --redirect -d powerdns.example.com
Now PowerDNS-Admin is installed and configured. Open your web browser and go to https://powerdns.example.com. You will be redirected to the PowerDNS-Admin web interface. Remember to create a user and then disable the option to register new accounts from the login page.
Conclusion
Congratulations! You have successfully installed and configured PowerDNS and PowerDNS-Admin on an Ubuntu 24.04 server. You can now host your domain and DNS zone records using the PowerDNS-Admin web interface.
Do you have any questions about this tutorial? Feel free to reach out. We’ll be happy to help 🙂