PDNS Manager

Installation

PDNS Manager runs as a Docker Compose stack of two containers: a Python/FastAPI backend (which also serves the built React frontend) and a MariaDB. There are three ways to set it up depending on how much hand-holding you want.

Requirements

  • Docker ≥ 20 with the Compose plugin (docker compose as a subcommand, not the legacy docker-compose).
  • A free port 5380 on the host. Change the ports: mapping in compose.yaml if it's already taken.
  • At least one running PowerDNS Authoritative server (4.x) with the HTTP API enabled – see below.
  • Optional: openssl on the host so the setup script can generate strong random secrets.

Option A · One-liner

The script clones the repo, asks a few questions, generates a complete .env with random passwords, starts the containers and waits for the healthcheck. Fastest path for 90 % of cases.

curl -sSLO https://raw.githubusercontent.com/29barra29/PowerDNS-PDNS-MANAGER/main/install.sh && bash install.sh

What it does, in order:

  1. Checks that it's interactive (warns on curl | bash without a TTY).
  2. Asks for the UI language (German / English).
  3. Verifies Docker, the Compose plugin, and that port 5380 is free (fallback chain lsof → ss → netstat).
  4. Picks an install path (default ./pdns-manager) and clones the repo – with a tarball fallback to the latest release tag if git is missing.
  5. Calls setup.sh for the .env.
  6. docker compose up -d, then actively polls http://localhost:5380/health (max 120 s).

Option B · Clone & setup wizard

Same outcome as A, just without the download wrapper:

git clone https://github.com/29barra29/PowerDNS-PDNS-MANAGER.git
cd dns-manager
./setup.sh
docker compose up -d

The wizard walks you through:

  • App name (branding, can be changed later in the panel).
  • Admin password: (1) random, (2) self-registration in the browser, (3) set manually.
  • SMTP optional – host, port, user, password, sender. (Stored in .env as MAIL_*; in production SMTP usually comes from the panel anyway, which lives in MariaDB.)
  • Will HTTPS sit in front later? Sets AUTH_COOKIE_SECURE accordingly.
  • First PowerDNS server optional – name, URL, API key. Can be added in the panel later.

The wizard writes .env atomically (via .env.tmp + mv, with a cleanup trap on Ctrl-C) and creates a timestamped backup beforehand.

Option C · Manual

For people who don't like wizards and want to set every variable themselves:

git clone https://github.com/29barra29/PowerDNS-PDNS-MANAGER.git
cd dns-manager
cp .env.example .env

# Mandatory: DB_ROOT_PASSWORD, DB_PASSWORD, JWT_SECRET_KEY
sed -i "s|^JWT_SECRET_KEY=.*|JWT_SECRET_KEY=$(openssl rand -hex 64)|" .env

nano .env
chmod 600 .env
docker compose up -d

First login

  1. Browser to http://localhost:5380 (or the server's IP).
  2. With ENABLE_REGISTRATION=true (the wizard default) the browser shows the setup wizard. The first user created becomes admin automatically; afterwards registration disables itself.
  3. If no password was set, the backend generates one on first start and stores it inside the container plus once in the log:
docker compose logs backend | grep -i "initial admin"
docker compose exec backend cat /app/.initial-admin-password

Enable the PowerDNS API

For the manager to talk to a PowerDNS server, its HTTP API has to be active. Minimal config in /etc/powerdns/pdns.conf:

api=yes
api-key=your-secure-api-key
webserver=yes
webserver-address=0.0.0.0
webserver-port=8081
webserver-allow-from=0.0.0.0/0

Then run systemctl restart pdns.

Add the PowerDNS server in the panel

In the panel under Settings → DNS servers → Add server:

  • Name – free display name.
  • URL – e.g. http://pdns.intern:8081, or via the container network http://pdns:8081.
  • API key – same value as in pdns.conf.
  • Writable? Leave on if the manager may push changes. With multiple PowerDNS instances on the same DB, mark only one as writable; the rest are pure read replicas.

Hit Test connection, save – done. Multiple servers are fine; the zone list automatically merges duplicates.

No image has been added yet. Drop it into src/assets/screenshots/<filename> and register it in the gallery list.

What lives on disk?

After start there are two volumes (default location /var/lib/docker/volumes/):

  • mariadb_data – the entire database including users, zone permissions, settings, tokens, audit log, webhooks.
  • backend_uploads – uploaded files (mainly the branding logo). Untouched by ./update.sh.

Containers are named dns-manager-api and dns-manager-db, network dns-manager-net.

Next steps