PowerDNS mit PowerDNS-Admin auf Debian 12 mit MariaDB

In dieser Anleitung installieren wir PowerDNS mit PowerDNS-Admin als WebGUI auf einem Debian 12. Als Backend kommt eine MariaDB zum Einsatz.

1. Als erstes installieren wir uns ein paar Dinge die wir brauchen:

$ sudo apt update
$ sudo apt -y install dnsutils curl gnupg gnupg1 gnupg2 git

2. MariaDB für PowerDNS intallieren/vorbereiten

Maria DB installieren:

$ sudo apt -y install mariadb-server

PowerDNS Datenbank anlegen, Datenbank Benutzer erstellen und Rechte gewähren.

$ sudo mysql -u root
CREATE DATABASE powerdns;
GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'strongpassword';
FLUSH PRIVILEGES;
QUIT;

Nun erstellen wir uns die Datei powerdns.sql mit folgendem Inhalt:

USE 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';

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);

 Jetzt kann die Datenbankstruktur erstellt werden:

$ sudo mysql -u root < powerdns.sql

3. Installation/Konfiguration von PowerDNS

$ sudo apt -y install pdns-server pdns-backend-mysql

Ist der Server installiert, konfigurieren wir PowerDNS, dass er die Datenbank als Backend nutzt.
Hierfür legen wir die Datei /etc/powerdns/pdns.d/pdns.local.gmysql.conf mit folgendem Inhalt an:

# MySQL Configuration
# Launch gmysql backend
launch+=gmysql
# gmysql parameters
gmysql-host=localhost
gmysql-port=3306
gmysql-dbname=powerdns
gmysql-user=powerdns
gmysql-password=strongpassword
gmysql-dnssec=yes

Um später mit PowerDNS-Admin auf unseren PowerDNS zugreifen zu können, müssen wir die API noch aktivieren und einen API-Key hinterlegen. Hierfür öffnen wir die Datei /etc/powerdns/pdns.conf und ändern folgende Einträge:

api=yes
api-key=verysecurekey

Und starten den PowerDNS-Dienst neu:

$ sudo systemctl restart pdns.service

 4. Installation von PowerDNS-Admin als WebGUI

Erstmal brauchen wir ein paar Packages:

$ sudo apt -y install python3-dev python3-venv python3-pip
$ sudo apt -y install default-libmysqlclient-dev python3-mysqldb libsasl2-dev libffi-dev libldap2-dev libssl-dev libxml2-dev libxslt1-dev libxmlsec1-dev pkg-config

Yarn installieren:

$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/yarnkey.gpg
$ 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 -y install yarn

Als nächstes holen wir uns die aktuellste Version von PowerDNS-Admin und wechseln in das Verzeichnis:

$ sudo git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git /opt/powerdns-admin
$ cd /opt/powerdns-admin

Dann erstellen wir uns eine VirtualEnv und installieren die Abhängigkeiten, die wir brauchen:

$ sudo python3 -m venv flask
$ sudo flask/bin/pip install -r requirements.txt

Nun bearbeiten wir die Datei powerdnsadmin/default_config.py und ändern die Einträge unter DATABASE CONFIG auf unsere Datenbank-Zugangdaten: 

SQLA_DB_USER = 'powerdns'
SQLA_DB_PASSWORD = 'strongpassword'
SQLA_DB_HOST = 'localhost'
SQLA_DB_NAME = 'powerdns'

Für die nächsten Schritte brauchen wir eine Umgebungsvariable, die root aber mit einem sudo nicht zur Verfügung steht. Daher machen wir uns jetzt ein wenig länger zu root:

$ sudo -s

Dann bereiten wir unsere Datenbank für PowerDNS-Admin vor.

$ export FLASK_APP=powerdnsadmin/__init__.py
$ flask/bin/flask db upgrade
$ flask/bin/flask db migrate -m "Init DB"

 Generieren die asset Dateien für yarn:

$ yarn install --pure-lockfile
$ flask/bin/flask assets build

 Nun können wir PowerDNS-Admin zum testen einmal starten:

$ flask/bin/python3 run.py

Der PowerDNS-Admin sollte jetzt unter http://Server-IP:9191 erreichbar sein.

Klickt unten auf der Loginseite auf Create an account um einen Account zu erstellen und loggt euch anschließend mit dem Account ein.

Nun werdet ihr aufgefordert, die PDNS Config fertig zu stellen.

Hier tragt ihr folgendes ein:

PDNS API URL: http://127.0.0.1:8081

PDNS API KEY: (Euren API-Key. Haben wir vorhin unter Schritt 3. in die /etc/powerdns/pdns.conf eingetragen)

Und unten auf den Button Update klicken.

Um zu verhindern, dass weitere Benutzer sich einen Account erstellen können, stellen wir noch die Selbstregistrierung ab:

Dazu entfernen wir den Hacken bei:

Settings -> Authentication -> General -> Allow users to sign up

Und drücken auf Save

Auf der Kommandozeile könnt ihr den Server jetzt mit Strg+C stoppen und exit eingeben um die root-Shell wieder zu verlassen.

5. PowerDNS-Admin als Dienst im systemd registrieren

Zuerst erstellen wir uns einen Benutzer, unter dem der Dienst später läuft:

$ sudo adduser --system --group --no-create-home --shell /bin/false pdns-admin

Dann legen wir unsere systemd-Service-Datei /etc/systemd/system/powerdns-admin.service mit folgendem Inhalt an:

[Unit]
Description=PowerDNS-Admin
After=network.target

[Service]
PIDFile=/run/powerdns-admin/pid
User=pdns-admin
Group=pdns-admin
WorkingDirectory=/opt/powerdns-admin
ExecStart=/opt/powerdns-admin/flask/bin/gunicorn --workers 1 --pid /run/powerdns-admin/pid --bind 0.0.0.0:9191 'powerdnsadmin:create_app()'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Jetzt braucht der Benutzer noch das Recht, ein PIDFile unter /run anzulegen. Dazu legen wir die Datei /etc/tmpfiles.d/powerdns-admin.conf mit folgendem Inhalt an:

d /run/powerdns-admin 0755 pdns-admin root -

Und einmal manuell ausführen: 

$ sudo systemd-tmpfiles --create /etc/tmpfiles.d/powerdns-admin.conf

Eigentümer von vom PowerDNS-Admin Verzeichnis ändern:

$ sudo chown -R pdns-admin. /opt/powerdns-admin

Jetzt können wir den Dienst starten:

$ sudo systemctl start powerdns-admin.service

Zum Schluss aktivieren wir den Dienst noch, damit unsere WebGUI auch nach einem Neustart des Linux gestartet wird:

$ sudo systemctl enable powerdns-admin.service

Viel Spaß mit eurem neuen DNS-Server... ;-)