PowerDNS application setups
This setup of PowerDNS brings up a full 2-node HA cluster one of them being primary, and will include pdns itself, but also pdns-recursor and dnsdist
It's meant to be setup with Rocky Linux 10, but it will generally work on many distributions, whith small tweaks to the documentation.
Documentation:
PowerDNS Authorative Server
PowerDNS Recursor
PowerDNS dnsdist
All cluster nodes - 1
- Setup a seperate IP for the authorative server and the frontend/dnsdist (2 per node)
- There will also be a floating VIP being deployed, so prepare this one too
dnf install setroubleshoot-server epel-releasecrb enablednf config-manager --add-repo https://repo.powerdns.com/repo-files/el-auth-51.repodnf config-manager --add-repo https://repo.powerdns.com/repo-files/el-rec-54.repodnf config-manager --add-repo https://repo.powerdns.com/repo-files/el-dnsdist-21.repodnf install postgresql-serverpostgresql-setup --initdb- Make sure authentication for PowerDNS is set to
scram-sha-256in thepg_hba.conffile systemctl enable --now postgresqldnf install pdns pdns-backend-postgresql pdns-recursor dnsdist- Create and populate the database:
su - postgres
psql
create database pdns;
\q
psql pdns < /usr/share/doc/pdns-backend-postgresql/schema.pgsql.sql
psql pdns
create user pdns with password '<secure-password>';
grant all on database pdns to pdns;
grant all on all tables in schema public to pdns;
grant all on all sequences in schema public to pdns;
\q
exit
- Change/Add the following parameters in
/etc/pdns/pdns.conf:
api=yes
api-key=<secure-api-key>
default-soa-content=<fqdn-of-primary> <hostname-of-hostmaster-record>.@ 0 10800 3600 604800 3600
default-soa-edit=INCEPTION-INCREMENT
launch=gpgsql
local-address=<ip-of-auth-server>
webserver-address=<ip-of-auth-server>
webserver-allow-from=127.0.0.1,::1,<powerdns-admin-ip>
gpgsql-host=127.0.0.1
gpgsql-dbname=pdns
gpgsql-user=pdns
gpgsql-password=<secure-password>
gpgsql-dnssec=yes
chown pdns:pdns /etc/pdns/pdns.conf
PowerDNS Authorative Server - primary
- Set
primary=trueadditionally in the/etc/pdns/pdns.conffile systemctl enable --now pdnspdnsutil create-zone <domain>pdnsutil set-kind <domain> primarypdnsutil set-meta <domain> API-RECTIFY 1pdnsutil set-meta <domain> SOA-EDIT-API DEFAULT- Edit the zone content with
EDITOR=vi pdnsutil edit-zone <domain>:
; Warning - every name in this file is ABSOLUTE!
$ORIGIN .
<domain> 3600 IN SOA <fqdn-of-primary> <fqdn-of-hostmaster-record> 0 10800 3600 604800 3600
<domain> 60 IN NS <fqdn-of-primary>
<domain> 60 IN NS <fqdn-of-secondary>
<fqdn-of-primary> 60 IN A <ip-of-primary>
<fqdn-of-secondary> 60 IN A <ip-of-primary>
pdnsutil secure-zone <domain>pdnsutil generate-tsig-key <keyname> <hmac-md5|hmac-shaX>pdnsutil activate-tsig-key <domain-to-sign> <keyname> primarypdnsutil show-zone <domain>to get the DS keys for later
PowerDNS Authorative Server - secondary
- Set
secondary=trueadditionally in the/etc/pdns/pdns.conffile systemctl enable --now pdnspdnsutil create-secondary-zone <domain> <ip-of-primary>pdnsutil import-tsig-key <keyname> <hmac-md5|hmac-shaX> '<base64-encoded-secret>'pdnsutil activate-tsig-key <domain-to-sign> <keyname> secondary- Make a change on the primary or run
pdns_control notify <domain>on the primary firewall-cmd --add-port=8081/tcpfirewall-cmd --add-port=8081/tcp --permanent
All cluster nodes - 2
- Setup the Recursor configuration as follows:
dnssec:
validation: log-fail
trustanchors:
- name: <domain>
dsrecords:
- <sha256-ds-string>
- <sha384-ds-string>
recursor:
include_dir: /etc/pdns-recursor/recursor.d
setuid: pdns-recursor
setgid: pdns-recursor
forward_zones:
- zone: <domain>
forwarders:
- <ip-of-auth-server>:53
incoming:
listen:
- 127.0.0.1:5300
- '[::1]:5353'
systemctl enable --now pdns-recursor- Setup the dnsdist configuration as follows:
acl:
- 0.0.0.0/0
binds:
- listen_address: "<ip-of-recursor>:53"
protocol: Do53
- listen_address: "<ip-of-vip>:53"
protocol: Do53
# - listen_address: "<ip-of-recursor>:443"
# protocol: DoH
# tls:
# certificates:
# - certificate: /etc/dnsdist/cert.pem
# key: /etc/dnsdist/privkey.pem
# - listen_address: "<ip-of-vip>:443"
# protocol: DoH
# tls:
# certificates:
# - certificate: /etc/dnsdist/cert.pem
# key: /etc/dnsdist/privkey.pem
# - listen_address: "<ip-of-recursor>:443"
# protocol: DoH3
# tls:
# certificates:
# - certificate: /etc/dnsdist/cert.pem
# key: /etc/dnsdist/privkey.pem
# - listen_address: "<ip-of-vip>:443"
# protocol: DoH3
# tls:
# certificates:
# - certificate: /etc/dnsdist/cert.pem
# key: /etc/dnsdist/privkey.pem
backends:
- address: "127.0.0.1:5300"
protocol: Do53
pools:
- default
query_rules:
- name: "default rule"
selector:
type: All
action:
type: Pool
pool_name: default
systemctl enable --now dnsdistfirewall-cmd --add-service={dns,https}firewall-cmd --add-service={dns,https} --permanent
Setup Pacemaker for floating VIP
dnf config-manager --enable highavailabilitydnf install which pacemaker pcs sbdecho softdog > /etc/modules-load.d/softdog.confmodprobe softdog- Set
SBD_DELAY_START=yesin the/etc/sysconfig/sbdfile firewall-cmd --add-service=high-availabilityfirewall-cmd --add-service=high-availability --permanentsystemctl enable --now pcsd sbdpasswd haclusterand set a secure passwordpcs host auth <fqdn-of-primary> <fqdn-of-secondary> <fqdn-of-secondary-n+1and enter the used passwordpcs cluster setup pdns --start <fqdn-of-primary> <fqdn-of-secondary> <fqdn-of-secondary-n+1pcs cluster enable --allpcs property set stonith-enabled=truepcs property set stonith-watchdog-timeout=20mkdir /usr/lib/ocf/resource.d/custom- Create a custom resource agent for pacemaker and safe to
/usr/lib/ocf/resource.d/custom/pdns_check:
#!/bin/bash
. /usr/lib/ocf/lib/heartbeat/ocf-shellfuncs
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="pdns_check">
<version>1.0</version>
<longdesc lang="en">
Checks PowerDNS availability via TCP and DNS query.
</longdesc>
<shortdesc lang="en">PowerDNS health check</shortdesc>
<parameters>
</parameters>
<actions>
<action name="start" timeout="5s" />
<action name="stop" timeout="5s" />
<action name="monitor" timeout="5s" interval="10s" />
<action name="meta-data" timeout="5s" />
</actions>
</resource-agent>
END
}
check() {
dig @<ip-of-auth-server> <fqdn-of-primary> +short +time=2 +tries=1 >/dev/null 2>&1 || return 1
dig @127.0.0.1 -p 5353 <fqdn-of-primary> +short +time=2 +tries=1 >/dev/null 2>&1 || return 1
dig @<ip-of-recursor> <fqdn-of-primary> +short +time=2 +tries=1 >/dev/null 2>&1 || return 1
return 0
}
case "$1" in
meta-data)
meta_data
exit 0
;;
start|stop)
exit 0
;;
monitor)
check || exit $OCF_ERR_GENERIC
exit 0
;;
status)
check
;;
*)
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
pcs resource create pdns_vip IPaddr2 ip=<ip-of-vip> cidr_netmask=24 op monitor interval=30spcs resource create pdns_check ocf:custom:pdns_check op monitor interval=10s timeout=5s meta migration-threshold=1 failure-timeout=30spcs constraint colocation add pdns_vip with pdns_check INFINITYpcs constraint order pdns_check then pdns_vippcs constraint location pdns_vip prefers <fqdn-of-primary>=100
PowerDNS-Admin
Documentation source: here and here
dnf install podmanmkdir /etc/containers/systemd/powerdns-admin- Create the following
/etc/containers/systemd/powerdns-admin/powerdns-admin.podfile:
[Pod]
PublishPort=127.0.0.1:9191:80
[Install]
WantedBy=default.target
- Create the following
/etc/containers/systemd/powerdns-admin/pda-legacy.containerfile:
[Unit]
Description=PowerDNS Admin
[Container]
AutoUpdate=registry
Pod=powerdns-admin.pod
Image=docker.io/powerdnsadmin/pda-legacy:latest
Volume=pda-data:/data
Environment=SECRET_KEY=<secret-key>
[Service]
TimeoutStartSec=900
systemctl daemon-reloadsystemctl start powerdns-admin-pod- Add nginx configuration in
/etc/nginx/conf.d/powerdns-admin.conf:
server {
listen <ip-of-auth-server>:80;
server_name <fqdn-of-primary>;
return 301 https://$host$request_uri;
}
server {
listen <ip-of-auth-server>:443 ssl;
http2 on;
server_name <fqdn-of-primary>;
index index.html index.htm
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
proxy_redirect off;
client_max_body_size 50m;
client_body_buffer_size 128k;
# Proxy headers
proxy_set_header Host $host;
proxy_set_header X-Scheme $scheme;
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;
# SSL parameters
ssl_certificate /path/to/cert.pem; # managed by Certbot
ssl_certificate_key /path/to/privkey.pem; # managed by Certbot
ssl_protocols TLSv1.2 TLSv1.3;
# log files
access_log /var/log/nginx/pda-access.log;
error_log /var/log/nginx/pda-error.log;
location / {
proxy_pass http://127.0.0.1:9191;
proxy_read_timeout 120;
proxy_connect_timeout 120;
}
}
systemctl enable --now nginxfirewall-cmd --add-service={http,https}firewall-cmd --add-service={http,https} --permanent- Go to web-frontend and register initial user
- Configure the connection to the powerdns system using the URI (port 8081), secret and version
- You might have to update the webserver allow list again, depending on your setup