Home PowerDNS Install with Web GUI and DB
Post
Cancel

PowerDNS Install with Web GUI and DB

Installing PowerDNS with PowerDNS-Admin on Debian 12


What is PowerDNS and How Can I Harness this Power

PowerDNS is a powerful, flexible authoritative DNS server that can be used to manage your domain’s DNS records programmatically. But sometimes you dont want to look at text and use a GUI instead. PowerDNS can be paired paired with PowerDNS-Admin, so you get a modern web interface for your DNS management.

In this write-up, we’ll walk through installing both PowerDNS and PowerDNS-Admin on Debian 12 (Bookworm). We’ll be using MariaDB to provide a database for both these services.

Proxmox’s new SDN uses PowerDNS for it’s DNS features, and so a PowerDNS LXC should be standard on most Proxmox multi-client/doamin setups.

And that’s what we’re doing today! By the end of this write-up, you’ll have a fully functional DNS server with a web-based management interface, complete with API access for Proxmox SDN’s DNS automation.


What Does This Write Up Talk About

  • PowerDNS Authoritative Server: A local DNS server, NOT one that does global lookups on the internet!
  • MariaDB Database: Backend storage for DNS records and application data
  • PowerDNS-Admin: A modern web interface for managing your DNS zones
  • REST API: Programmatic access to your DNS infrastructure, essential for Proxmox SDN’s DNS automation with PowerDNS
  • Multi-tenant Support: Ready for Proxmox multi-client and Proxmox multi-domain deployments

🏁 Speedrun This Process with a Script

If like to download scripts from the internet - you’re in luck!

I have, at the bottom of this post, a - 🎚️ PowerDNS EZ-MODE script.

This script will complete the entire write-up for you! Just be sure to change the config variables first.

Please continue on to go through the steps of setting up PowerDNS to use MariaDB, then PowerDNS-Admin.


Part 1: System Preparation and MariaDB Installation

Step 1: Update Your System

Let’s start by ensuring your system is up to date:

1
apt update && apt upgrade -y

Step 2: Install Essential Dependencies

Install the core packages we’ll need throughout this process:

1
apt install -y sudo curl git libpq-dev software-properties-common gnupg2

Step 3: Install MariaDB

MariaDB will serve as the database backend for both PowerDNS (storing DNS records for your Proxmox multi-domain environments) and PowerDNS-Admin (storing users and settings).

First, download and install the official MariaDB repository setup script:

1
curl -LsS -o mariadb_repo_setup https://downloads.mariadb.com/MariaDB/mariadb_repo_setup && echo "$(curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup.sha256)" > mariadb_repo_setup.sha256 && sha256sum -c mariadb_repo_setup.sha256 && sudo bash mariadb_repo_setup && rm mariadb_repo_setup mariadb_repo_setup.sha256

Now install MariaDB server and client:

1
sudo apt update && sudo apt install -y mariadb-server mariadb-client

Start and enable the MariaDB service to run on boot:

1
sudo systemctl enable --now mariadb

Step 4: Secure Your MariaDB Installation

For new MariaDB installations, the next step is to run a security script. This script changes some of the less secure default options for things like remote root logins and sample users.

Optionally, run the security script to improve your database security posture:

1
sudo mysql_secure_installation

I answered, no to the first two, defaults for everything else.

I used the following answers:

1
2
3
4
5
6
Switch to unix_socket authentication [Y/n] n
Change the root password? [Y/n] n
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

Step 5: Create Database and User

Now we’ll create the databases and user account that PowerDNS and PowerDNS-Admin will use.

Important Note: Avoid special characters in the password, as PowerDNS has been known to have issues with certain special characters, which can result in authentication errors: “Access denied for user ‘powerdns_user’@’localhost’ (using password: YES)“

For this guide, we’ll use:

  • Username: powerdnsmariaccessuser
  • Password: MikeJohnsonLikes9091Hamburgers
  • PowerDNS Database: powerdns
  • PowerDNS-Admin Database: powerdnsadmin

Log into MariaDB as root:

1
sudo mysql -u root

Execute the following SQL commands:

1
2
3
4
5
6
7
8
9
CREATE DATABASE powerdns;
CREATE DATABASE powerdnsadmin;

CREATE USER 'powerdnsmariaccessuser'@'localhost' IDENTIFIED BY 'MikeJohnsonLikes9091Hamburgers';

GRANT ALL PRIVILEGES ON *.* TO 'powerdnsmariaccessuser'@'localhost';

FLUSH PRIVILEGES;
EXIT

Part 2: Installing PowerDNS

Step 6: Add the PowerDNS Repository

To get the latest version of PowerDNS (version 5.0 as of writing), we’ll add the official PowerDNS repository. This ensures we’re running the most current and secure version: https://doc.powerdns.com/authoritative/installation.html

You have to install their repository:

https://repo.powerdns.com/

Create the repository configuration:

1
2
3
printf "deb [signed-by=/etc/apt/keyrings/auth-50-pub.asc] http://repo.powerdns.com/debian bookworm-auth-50 main" > /etc/apt/sources.list.d/pdns.list

printf "Package: pdns-*\nPin: origin repo.powerdns.com\nPin-Priority: 600" > /etc/apt/preferences.d/auth-50

Add the GPG key and install PowerDNS:

1
2
3
4
sudo install -d /etc/apt/keyrings; curl https://repo.powerdns.com/FD380FBB-pub.asc | sudo tee /etc/apt/keyrings/auth-50-pub.asc &&
sudo apt-get update &&
sudo apt-get install pdns-server

Step 7: Verify PowerDNS is Running

Verify the port 53 is open for PowerDNS to provide DNS:

1
sudo ss -alnp4 | grep pdns

You should see output showing PowerDNS listening on port 53.


Part 3: Configuring PowerDNS with MariaDB

Step 8: Install the MariaDB Backend

PowerDNS supports multiple database backends. Install the MariaDB/MySQL backend to enable an easy-to-backup database for your Proxmox multi-domain DNS zones:

1
sudo apt install pdns-backend-mysql

Step 9: Initialize the PowerDNS Database Schema

Import the database schema that PowerDNS needs to store DNS records:

1
2
3
mariadb --user=powerdnsmariaccessuser \
        --password=MikeJohnsonLikes9091Hamburgers \
        --database=powerdns < /usr/share/pdns-backend-mysql/schema/schema.mysql.sql

Verify the schema was imported successfully:

1
2
3
4
sudo mysql -u root
use powerdns;
show tables;
exit

You should see several tables including domains, records, and cryptokeys.

Step 10: Configure PowerDNS Database Connection

Create a configuration file that tells PowerDNS how to connect to MariaDB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo bash -c 'cat <<EOF > /etc/powerdns/pdns.d/pdns.local.gmysql.conf
# MySQL Configuration
# Launch gmysql backend
launch+=gmysql

# gmysql parameters
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=powerdns
gmysql-user=powerdnsmariaccessuser
gmysql-password=MikeJohnsonLikes9091Hamburgers
#gmysql-dnssec=yes
# gmysql-socket=
EOF'

Set the appropriate permissions on this configuration file:

1
2
sudo chown pdns: /etc/powerdns/pdns.d/pdns.local.gmysql.conf
sudo chmod 640 /etc/powerdns/pdns.d/pdns.local.gmysql.conf

Step 11: Test the Database Connection

Stop the PowerDNS service:

1
sudo systemctl stop pdns.service

Run PowerDNS in the foreground with verbose logging to verify the database connection:

1
sudo pdns_server --daemon=no --guardian=no --loglevel=9

You should see log output indicating a successful database connection. Press Ctrl+C to stop the server.

If successful, restart PowerDNS as a service and enable it to start on boot:

1
sudo systemctl restart pdns && sudo systemctl enable --now pdns

Step 12: Verify PowerDNS is Working

Check that PowerDNS is responding to DNS queries:

1
dig @127.0.0.1

Part 4: Installing PowerDNS-Admin

PowerDNS-Admin is a web-based interface that makes managing your DNS server much easier, especially in Proxmox multi-client environments where multiple administrators need access. It’s built with Python Flask and requires Node.js for asset compilation.

Step 13: Install Python and Build Dependencies

Install the necessary packages for building alllllllll the Python libraries:

1
sudo apt install -y apt-transport-https build-essential curl git libffi-dev libldap2-dev libmariadb-dev libpq-dev libsasl2-dev libssl-dev libxml2-dev libxmlsec1-dev libxslt1-dev pkg-config python3-dev python3-flask python3-venv virtualenv

Step 14: Install Node.js

Add the NodeSource repository for Node.js 20.x to get npm:

1
curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash -

Install Node.js (npm is included automatically):

1
sudo apt install -y nodejs

Important: Do not install npm separately from Debian’s repositories—it’s outdated and broken. Always use NodeSource or nvm.

Verify the installation:

1
npm -v

Step 15: Install Yarn

Yarn is a package manager we’ll use to build the frontend assets:

1
2
3
4
5
6
7
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | \
    sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | \
    sudo tee /etc/apt/sources.list.d/yarn.list

sudo apt update && sudo apt install -y yarn

Step 16: Clone and Set Up PowerDNS-Admin

Clone the PowerDNS-Admin repository:

1
2
git clone https://github.com/PowerDNS-Admin/PowerDNS-Admin.git /opt/web/powerdns-admin
cd /opt/web/powerdns-admin

Create a Python virtual environment:

1
python3 -m venv ./venv

Activate the virtual environment and install Python dependencies:

1
2
3
source ./venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt

Step 17: Configure PowerDNS-Admin

Deactivate the virtual environment temporarily:

1
deactivate

Copy the development configuration to create a production config:

1
cp /opt/web/powerdns-admin/configs/development.py /opt/web/powerdns-admin/configs/production.py

Generate a secret key for Flask sessions:

1
python3 -c 'import secrets; print(secrets.token_hex())' 'ToddHowardLikes4126Turkeysammies'

Copy the output—you’ll need it in the next step.

Edit the production configuration:

1
nano /opt/web/powerdns-admin/configs/production.py

Find and update the database configuration section:

1
2
3
4
5
6
7
8
9
# Change from:
SQLA_DB_USER = 'pda'
SQLA_DB_PASSWORD = 'changeme'
SQLA_DB_NAME = 'pda'

# To:
SQLA_DB_USER = 'powerdnsmariaccessuser'
SQLA_DB_PASSWORD = 'MikeJohnsonLikes9091Hamburgers'
SQLA_DB_NAME = 'powerdnsadmin'

Scroll down to find the SQLite database URI section and update it:

1
2
3
4
5
# Comment out the SQLite line:
# SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db')

# Add the MySQL connection string:
SQLALCHEMY_DATABASE_URI = 'mysql://powerdnsmariaccessuser:MikeJohnsonLikes9091Hamburgers@127.0.0.1/powerdnsadmin'

Also, add your generated secret key to the SECRET_KEY variable in this file.

Save and close the file.

Step 18: Initialize the Application

Set up the Flask environment:

1
2
3
cd /opt/web/powerdns-admin
source ./venv/bin/activate
export FLASK_CONF=../configs/production.py

Run database migrations:

1
2
export FLASK_APP=powerdnsadmin/__init__.py
flask db upgrade

Generate frontend assets:

1
2
yarn install --pure-lockfile
flask assets build

Step 19: Test PowerDNS-Admin

You can now test the application:

1
./run.py

Visit http://your-server-ip:9191 in your web browser. You should see a registration page.

Important Notes:

  • Disable any ad blockers or script blockers while accessing the interface
  • On that page - you need to register your first user, that first user will automatically be granted Administrator rights.
  • After registration, you’ll be redirected to the login page—this is normal. Yes, it worked. You got no afirmation of user creation, you just got re-directed back to the login page. Use your newly created credentials.

When testing is complete, press Ctrl+C and deactivate the virtual environment:

1
deactivate

Part 5: Enabling the PowerDNS API

The PowerDNS API is crucial for API access for Proxmox SDN’s DNS automation with PowerDNS. This allows PowerDNS-Admin and Proxmox SDN to manage your DNS records programmatically, enabling seamless integration with your virtualization infrastructure.

Step 20: Generate an API Key

You can generate a secure API key at https://codepen.io/corenominal/pen/rxOmMJ or use any UUID generator.

For this guide, we’ll use: 135af146-c29c-4dd6-8608-14b3c0386ae9

Step 21: Configure the API

Edit the main PowerDNS configuration file:

1
sudo nano /etc/powerdns/pdns.conf

Add or uncomment these lines to enable API access for Proxmox SDN’s DNS automation with PowerDNS and PowerDNS-Admin:

1
2
3
4
5
6
7
8
9
#################################
# api   Enable/disable the REST API (including HTTP listener)
#
api=yes

#################################
# api-key       Static pre-shared authentication key for access to the REST API
#
api-key=135af146-c29c-4dd6-8608-14b3c0386ae9

Save the file and restart PowerDNS:

1
sudo systemctl restart pdns

Step 22: Clean Up Configuration Issues

Some PowerDNS configurations may contain invalid directives. Check your configuration directory:

1
cd /etc/powerdns/pdns.d/

If you have a bind.conf file, edit it:

1
sudo nano bind.conf

Remove or comment out any lines except the first one (typically launch+=bind). The bind-config directive may not be valid in your version and should be removed.


Part 6: Creating a System Service

To be able to manage PowerDNS Admin just like other system services, we need to create a service file for it.

Step 23: Create the Service File

1
sudo nano /etc/systemd/system/pdnsadmin.service

Add the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Unit]
Description=PowerDNS-Admin
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/web/powerdns-admin
User=root
Group=root

# Environment variable for Flask config
Environment=FLASK_CONF=../configs/production.py

# Use the python interpreter inside your virtual environment
ExecStart=/opt/web/powerdns-admin/venv/bin/python /opt/web/powerdns-admin/run.py

Restart=on-failure

[Install]
WantedBy=multi-user.target

Step 24: Create the Socket File

Also, create a socket file:

1
sudo nano /etc/systemd/system/pdnsadmin.socket

Add these lines:

1
2
3
4
5
6
7
8
[Unit]
Description=PowerDNS-Admin socket

[Socket]
ListenStream=/run/pdnsadmin/socket

[Install]
WantedBy=sockets.target

Step 25: Set Up Runtime Directory

Create the runtime directory and configure it to persist across reboots:

1
2
mkdir -p /run/pdnsadmin/
echo "d /run/pdnsadmin 0755 pdns pdns -" >> /etc/tmpfiles.d/pdnsadmin.conf

Step 26: Set Permissions

1
2
chown -R pdns: /run/pdnsadmin/
chown -R pdns: /opt/web/powerdns-admin

Step 27: Enable and Start the Service

Reload systemd to recognize the new service:

1
systemctl daemon-reload

Enable and start the PowerDNS-Admin service:

1
systemctl enable --now pdnsadmin.service pdnsadmin.socket

Check the service status:

1
systemctl status pdnsadmin.service pdnsadmin.socket

Part 7: Connecting PowerDNS-Admin to PowerDNS

Step 28: Configure the API Connection

  1. Log into the PowerDNS-Admin web interface at http://your-server-ip:9191
  2. Navigate to the settings or configuration section
  3. Add your PowerDNS server with:
    • API URL: http://your-server-ip:8081
    • API Key: 135af146-c29c-4dd6-8608-14b3c0386ae9 (the key from your pdns.conf)

Once connected, you’ll be able to create and manage DNS zones through the web interface!


Part 8: Integrating with Proxmox SDN

Since Proxmox SDN uses PowerDNS for its DNS features, your installation is now ready for Proxmox integration. Here’s how to leverage your PowerDNS setup with Proxmox VE:

Configuring Proxmox SDN DNS Integration

  1. In Proxmox VE, navigate to Datacenter → SDN → DNS
  2. Add DNS Server with these settings:
    • Type: PowerDNS
    • Server: Your PowerDNS server IP
    • API URL: http://your-powerdns-ip:8081
    • API Key: 135af146-c29c-4dd6-8608-14b3c0386ae9

Benefits for Proxmox Multi-Client Environments

Your PowerDNS setup now enables:

  • Automatic DNS record creation when VMs are deployed in Proxmox SDN zones
  • Proxmox multi-client support through PowerDNS-Admin’s user management and role-based access control
  • Centralized DNS management across multiple Proxmox clusters
  • API-driven automation for infrastructure-as-code deployments

Benefits for Proxmox Multi-Domain Configurations

The database-backed PowerDNS installation provides:

  • Multiple DNS zones for different departments or customers
  • Domain delegation capabilities for Proxmox multi-domain setups
  • Consistent DNS management across all your Proxmox environments
  • Scalable architecture that grows with your infrastructure

And remember… if there’s any problems, it’s never the DNS.


🎚️ PowerDNS EZ-MODE script

But if you are having problems, just use the script below.

You need to make a few changes before running it:

PowerDNS and PowerDNS Admin with MariaDB Script Configuration Overview

Before running the script, update the variables below to match your environment:

VariablePurposeExample Value
DB_USERDatabase username for PowerDNS & PowerDNS-Adminpowerdnsmariaccessuser
DB_PASSWORDDatabase password for the above userTableSauceisnotRefrigerated1987
PDNS_DB_NAMEDatabase name used by PowerDNSpowerdns
PDNSADMIN_DB_NAMEDatabase name used by PowerDNS-Adminpowerdnsadmin
PDNS_API_KEYSecret key for PowerDNS API135af146-c29c-4dd6-8608-14b3c0386ae9
PDNSADMIN_PATHInstallation path (no need to change)/opt/web/powerdns-admin
FLASK_SECRET_KEYSecret for securing web sessions (ok if empty)leave empty to auto-generate

PowerDNS and PowerDNS Admin with MariaDB Script

Please be sure to make changes to the configuration variables below. Enjoy PowerDNS using MariaDB!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
#!/bin/bash

#############################################
# PowerDNS & PowerDNS-Admin Installation Script
# For Debian 12 (Bookworm)
#############################################

#############################################
# CONFIGURATION VARIABLES - EDIT THESE
#############################################

# Database Configuration
# Please change the DB_USER and DB_PASSWORD to something unique you can remember
DB_USER="powerdnsmariaccessuser"
DB_PASSWORD="MikeJohnsonLikes9091Hamburgers"
PDNS_DB_NAME="powerdns"
PDNSADMIN_DB_NAME="powerdnsadmin"

# PowerDNS API Configuration
# You can generate an API key at https://codepen.io/corenominal/pen/rxOmMJ
PDNS_API_KEY="135af146-c29c-4dd6-8608-14b3c0386ae9"

# PowerDNS-Admin Installation Path
PDNSADMIN_PATH="/opt/web/powerdns-admin"

# Flask Secret Key (auto-generated if left empty)
FLASK_SECRET_KEY=""

#############################################
# PRE-FLIGHT CHECKS
#############################################

# Ensure the script is run as root (via sudo or directly)
if [[ $EUID -ne 0 ]]; then
  echo "This script must be run as root. Re-running with sudo..."
  exec sudo "$0" "$@"
fi

# Exit on any error
set -e

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Function to print colored output
print_status() {
    echo -e "${GREEN}[✓]${NC} $1"
}

print_error() {
    echo -e "${RED}[✗]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[!]${NC} $1"
}

# Tray tables in the upright position
print_status "Starting PowerDNS installation script..."

# Check if Debian 12
if ! grep -q "bookworm" /etc/os-release; then
    print_warning "This script is designed for Debian 12 (Bookworm). Proceeding anyway..."
fi

#############################################
# SYSTEM PREPARATION
#############################################

print_status "Updating system packages..."
apt update && apt upgrade -y

print_status "Installing essential dependencies..."
apt install -y sudo curl git libpq-dev software-properties-common gnupg2

#############################################
# MARIADB INSTALLATION
#############################################

print_status "Installing MariaDB repository..."
curl -LsS -o mariadb_repo_setup https://downloads.mariadb.com/MariaDB/mariadb_repo_setup && echo "$(curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup.sha256)" > mariadb_repo_setup.sha256 && sha256sum -c mariadb_repo_setup.sha256 && sudo bash mariadb_repo_setup && rm mariadb_repo_setup mariadb_repo_setup.sha256

print_status "Installing MariaDB server and client..."

apt update && DEBIAN_FRONTEND=noninteractive apt-get install -y mariadb-server

print_status "Starting and enabling MariaDB..."
systemctl enable --now mariadb

print_status "Securing MariaDB installation..."
# Automate mysql_secure_installation
mysql -u root <<EOF
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
EOF

print_status "Creating PowerDNS databases and user..."
mysql -u root <<EOF
CREATE DATABASE IF NOT EXISTS ${PDNS_DB_NAME};
CREATE DATABASE IF NOT EXISTS ${PDNSADMIN_DB_NAME};
CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASSWORD}';
GRANT ALL PRIVILEGES ON *.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
EOF

#############################################
# POWERDNS INSTALLATION
#############################################

print_status "Adding PowerDNS repository..."
printf "deb [signed-by=/etc/apt/keyrings/auth-50-pub.asc] http://repo.powerdns.com/debian bookworm-auth-50 main" > /etc/apt/sources.list.d/pdns.list
printf "Package: pdns-*\nPin: origin repo.powerdns.com\nPin-Priority: 600" > /etc/apt/preferences.d/auth-50

install -d /etc/apt/keyrings
curl https://repo.powerdns.com/FD380FBB-pub.asc | tee /etc/apt/keyrings/auth-50-pub.asc > /dev/null

print_status "Installing PowerDNS server..."
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y pdns-server

print_status "Installing PowerDNS MySQL backend..."
DEBIAN_FRONTEND=noninteractive apt-get install -y pdns-backend-mysql

#############################################
# POWERDNS CONFIGURATION
#############################################

print_status "Importing PowerDNS database schema..."
mariadb --user=${DB_USER} --password=${DB_PASSWORD} --database=${PDNS_DB_NAME} < /usr/share/pdns-backend-mysql/schema/schema.mysql.sql

print_status "Configuring PowerDNS database connection..."
cat > /etc/powerdns/pdns.d/pdns.local.gmysql.conf <<EOF
# MySQL Configuration
# Launch gmysql backend
launch+=gmysql

# gmysql parameters
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=${PDNS_DB_NAME}
gmysql-user=${DB_USER}
gmysql-password=${DB_PASSWORD}
#gmysql-dnssec=yes
EOF

chown pdns: /etc/powerdns/pdns.d/pdns.local.gmysql.conf
chmod 640 /etc/powerdns/pdns.d/pdns.local.gmysql.conf

print_status "Enabling PowerDNS API..."
# Backup original config
cp /etc/powerdns/pdns.conf /etc/powerdns/pdns.conf.backup

# Add API configuration
cat >> /etc/powerdns/pdns.conf <<EOF

#################################
# API Configuration
#################################
api=yes
api-key=${PDNS_API_KEY}
webserver=yes
webserver-address=127.0.0.1
webserver-port=8081
webserver-allow-from=127.0.0.1,::1
EOF

print_status "Cleaning up bind.conf if it exists..."
if [ -f /etc/powerdns/pdns.d/bind.conf ]; then
    # Keep only the launch line
    sed -i '/^launch/!d' /etc/powerdns/pdns.d/bind.conf
fi

print_status "Starting PowerDNS..."
systemctl restart pdns
systemctl enable pdns

# Verify PowerDNS is running
if systemctl is-active --quiet pdns; then
    print_status "PowerDNS is running successfully"
else
    print_error "PowerDNS failed to start"
    systemctl status pdns
    exit 1
fi

## Assigning Version Number
PDNS_VERSION=$(pdns_server --version | grep "PowerDNS Authoritative Server" | awk '{print $4}')

#############################################
# POWERDNS-ADMIN DEPENDENCIES
#############################################

print_status "Installing PowerDNS-Admin build dependencies..."
apt install -y apt-transport-https build-essential curl git \
    libffi-dev libldap2-dev libmariadb-dev libpq-dev libsasl2-dev \
    libssl-dev libxml2-dev libxmlsec1-dev libxslt1-dev pkg-config \
    python3-dev python3-flask python3-venv virtualenv

print_status "Installing Node.js 20.x..."
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs

print_status "Installing Yarn..."
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | tee /etc/apt/sources.list.d/yarn.list
apt update && apt install -y yarn

#############################################
# POWERDNS-ADMIN INSTALLATION
#############################################

print_status "Cloning PowerDNS-Admin repository..."
if [ -d "$PDNSADMIN_PATH" ]; then
    print_warning "PowerDNS-Admin directory already exists. Backing up..."
    mv "$PDNSADMIN_PATH" "${PDNSADMIN_PATH}.backup.$(date +%Y%m%d_%H%M%S)"
fi

git clone https://github.com/PowerDNS-Admin/PowerDNS-Admin.git "$PDNSADMIN_PATH"
cd "$PDNSADMIN_PATH"

print_status "Creating Python virtual environment..."
python3 -m venv ./venv

print_status "Installing Python dependencies..."
source ./venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
deactivate

#############################################
# POWERDNS-ADMIN CONFIGURATION
#############################################

print_status "Creating PowerDNS-Admin production configuration..."
cp configs/development.py configs/production.py

# Generate Flask secret key if not provided
if [ -z "$FLASK_SECRET_KEY" ]; then
    FLASK_SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_hex())')
    print_status "Generated Flask secret key: $FLASK_SECRET_KEY"
fi

# Update production config
sed -i "s/SQLA_DB_USER = .*/SQLA_DB_USER = '${DB_USER}'/" configs/production.py
sed -i "s/SQLA_DB_PASSWORD = .*/SQLA_DB_PASSWORD = '${DB_PASSWORD}'/" configs/production.py
sed -i "s/SQLA_DB_NAME = .*/SQLA_DB_NAME = '${PDNSADMIN_DB_NAME}'/" configs/production.py

# Update SQLAlchemy URI
sed -i "s|^SQLALCHEMY_DATABASE_URI = 'sqlite.*|# SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db')\nSQLALCHEMY_DATABASE_URI = 'mysql://${DB_USER}:${DB_PASSWORD}@127.0.0.1/${PDNSADMIN_DB_NAME}'|" configs/production.py

# Add secret key if not already present
if ! grep -q "^SECRET_KEY = " configs/production.py; then
    echo "SECRET_KEY = '${FLASK_SECRET_KEY}'" >> configs/production.py
else
    sed -i "s/SECRET_KEY = .*/SECRET_KEY = '${FLASK_SECRET_KEY}'/" configs/production.py
fi

print_status "Initializing PowerDNS-Admin database..."
source ./venv/bin/activate
export FLASK_CONF=../configs/production.py
export FLASK_APP=powerdnsadmin/__init__.py
flask db upgrade

print_status "Building frontend assets..."
yarn install --pure-lockfile
flask assets build
deactivate

#############################################
# SYSTEMD SERVICE CONFIGURATION
#############################################

print_status "Creating systemd service files..."

cat > /etc/systemd/system/pdnsadmin.service <<EOF
[Unit]
Description=PowerDNS-Admin
After=network.target

[Service]
Type=simple
WorkingDirectory=${PDNSADMIN_PATH}
User=pdns
Group=pdns

Environment=FLASK_CONF=../configs/production.py

ExecStart=${PDNSADMIN_PATH}/venv/bin/python ${PDNSADMIN_PATH}/run.py

Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

cat > /etc/systemd/system/pdnsadmin.socket <<EOF
[Unit]
Description=PowerDNS-Admin socket

[Socket]
ListenStream=/run/pdnsadmin/socket

[Install]
WantedBy=sockets.target
EOF

print_status "Setting up runtime directory..."
mkdir -p /run/pdnsadmin/
echo "d /run/pdnsadmin 0755 pdns pdns -" > /etc/tmpfiles.d/pdnsadmin.conf

print_status "Setting permissions..."
chown -R pdns: /run/pdnsadmin/
chown -R pdns: "$PDNSADMIN_PATH"

print_status "Enabling and starting PowerDNS-Admin service..."
systemctl daemon-reload
systemctl enable --now pdnsadmin.service pdnsadmin.socket

# Wait a few moments for the service to start
sleep 6

# Check if service is running
if systemctl is-active --quiet pdnsadmin.service; then
    print_status "PowerDNS-Admin is running successfully"
else
    print_error "PowerDNS-Admin failed to start"
    systemctl status pdnsadmin.service
fi

# Wait a few more moments to be sure the service to started and doesnt spew text to the terminal
sleep 6

#############################################
# INSTALLATION COMPLETE
#############################################

echo ""
echo "=========================================="
print_status "Installation Complete!"
echo "=========================================="
echo ""
echo "Next Steps:"
echo "  1. Visit PowerDNS-Admin web interface"
echo "     - http://$(hostname -I | awk '{print $1}'):9191"
echo "  2. Register your first user"
echo "  3. In PowerDNS-Admin setup, add your PowerDNS server:"
echo "     - API URL: http://127.0.0.1:8081"
echo "     - API Key: ${PDNS_API_KEY}"
echo "     - Version: ${PDNS_VERSION}"
echo ""
echo "----------------------------------------------"
echo "PowerDNS Configuration:"
echo "  - Database: ${PDNS_DB_NAME}"
echo "  - API URL: http://$(hostname -I | awk '{print $1}'):8081"
echo "  - API Key: ${PDNS_API_KEY}"
echo "  - Version: ${PDNS_VERSION}"
echo ""
echo "PowerDNS-Admin Configuration:"
echo "  - Web Interface: http://$(hostname -I | awk '{print $1}'):9191"
echo "  - Database: ${PDNSADMIN_DB_NAME}"
echo "  - Installation Path: ${PDNSADMIN_PATH}"
echo ""
echo "Database User:"
echo "  - Username: ${DB_USER}"
echo "  - Password: ${DB_PASSWORD}"
echo ""
echo "Service Status:"
echo "  - PowerDNS: $(systemctl is-active pdns)"
echo "  - PowerDNS-Admin: $(systemctl is-active pdnsadmin)"
echo ""
echo "=========================================="

This post is licensed under CC BY 4.0 by the author.