Open Source · Debian 13 · Python 3.13

A PowerDNS web interface,
re-targeted for modern Debian

PowerDNS-Admin is a fork of PowerDNS-Admin/PowerDNS-Admin by Kynoci — re-targeted at bare-metal Debian 13 (trixie) with Python 3.13, a tighter source tree, a strict-typed library layer, scripted bare-metal install, and a faster local-dev loop. Newer PowerDNS Authoritative Server 4.x and 5.x are both supported.

https://pdns-admin.local/zone/dashboard
This fork · v0.5.3 Upstream · v0.4.2 PowerDNS-Admin dashboard, this fork v0.5.3
PowerDNS-Admin dashboard, upstream v0.4.2

Drag the slider to compare upstream v0.4.2 with this fork's v0.5.3 — or use when focused.

What you get out of the box

Everything the upstream project gave you for managing PowerDNS — plus a cleaner install, headless provisioning, and a modern Debian target.

Zone & Record Editor

The full Knockout-powered zone-record table from upstream — add, edit, and delete records with inline validation, batched commits, and a per-zone changelog.

Multi-Backend Auth

Local accounts, LDAP, SAML, and OAuth (Google / GitHub / Microsoft / Azure / OIDC). Providers now stored under current_app.extensions instead of module globals.

Typed JSON API

The routes/api.py mega-module is split into per-resource files (zones, apikeys, users, accounts, dnssec, proxy). Schemas migrated from lima to marshmallow; OpenAPI spec at /api/v1/openapi.{json,yaml} via apispec.

Sidebar Accordion + Breadcrumbs

Sidebar redone as a Bootstrap-4 accordion (Zone Management / Administration / Server Settings — one open at a time). Breadcrumbs auto-derived from URL segments — no per-template hand-written <ol>.

First-Run Security Gate

App refuses to serve traffic if SECRET_KEY / SALT / SQLA_DB_PASSWORD still match source-tree defaults. Bypass for local dev with PDA_ALLOW_INSECURE_DEFAULTS=1 (logged loudly).

Headless Provisioning CLIs

flask init-secrets, flask create-admin, flask set-server-setting — bring an install up without a human ever logging in. Designed for Ansible, Terraform, and immutable images.

Scripted Bare-Metal Install

Four idempotent install scripts: PDA itself, PowerDNS auth (sqlite or MySQL), and an optional recursor. System deps, venv, frontend assets, db upgrade, admin user, API settings, and a systemd unit — all wired up.

Strict Typing on lib/

mypy --strict runs in CI on the pure-helper layer (errors, record diff, record builder, external-provisioning helper, to_idna). The rest of lib/ is on a relaxed list pending follow-up.

Partitioned Test Suite

pytest -m unit — 152 pure-function tests, ~0.3 s. pytest -m integration — 56 tests, needs live pdns-auth (brought up by scripts/setup-pdns-test.sh). Both wired into GitHub Actions.

Operability, URL surface, UI, backend

This fork is downstream cleanup, URL polish, and operability changes. The underlying product is still PowerDNS-Admin — the zone editor, OAuth/SAML/LDAP, and JSON API all came from there.

Three-command local dev flow

No more FLASK_APP / FLASK_CONF plumbing. run.py auto-applies Alembic migrations on boot, and create_app auto-loads <repo_root>/config.py if present.

  • Python package renamed powerdnsadminpdnsadmin — product name preserved everywhere it was a label
  • Settings panes moved off admin_bp into a dedicated setting_bp; zone CRUD into zone_bp
  • HTMX shipped in the asset bundle; zone-editor changelog already uses hx-boost
  • Explicit ENV_PINNED_KEYS registry — bootstrap secrets, Flask-Mail, Flask-Session, SAML transport keys skip the DB and stay in app.config; the admin UI refuses to write them
  • Tested on the latest Debian: Debian 13 (trixie) with Python 3.13
# clone, install, run — three commands $ cd /opt/powerdns-admin $ source .venv/bin/activate $ ./run.py # headless provisioning $ flask init-secrets $ flask create-admin --username admin \ --email admin@example.com \ --password '<set-me>' $ flask set-server-setting --api-url http://127.0.0.1:8081 \ --api-key '<k>' --pdns-ver 4

Paths read like the UI labels

The visible URL surface was reorganised. Old paths return 404 — bookmarks need updating.

BeforeAfter
/dashboard/zone/dashboard
/domain/add/zone/create
/domain/remove/zone/remove
/admin/global-search/admin/search
/admin/history/admin/activity
/admin/server/statistics/admin/statistics
/admin/server/configuration/admin/configuration
/admin/manage-account/admin/account
/admin/manage-user/admin/user
/admin/manage-keys/admin/keys
/admin/setting/basic/setting/config
/admin/setting/dns-records/setting/record
/admin/setting/pdns/setting/server
/admin/setting/authentication/setting/auth

Bring up PowerDNS + PDA in two scripts

Bare-metal Debian 13. The first script installs PowerDNS auth + the chosen backend on port 5300 (API on 8081); the second installs PDA itself.

1. Install PowerDNS authoritative + backend

Pick a backend — sqlite for a quick try, MySQL for production-shaped tests:

$ sudo ./docs/install-002-pdns-auth-sqlite.sh # or: sudo ./docs/install-004-pdns-auth-mysql.sh

2. Install PowerDNS-Admin

System deps, venv, frontend build, Alembic migrations, the local admin user, the PDNS API connection settings, and a pdnsadmin.service systemd unit on port 9191:

$ sudo ./docs/install-001-powerdns-admin.sh

3. (Optional) Install a local recursor

$ sudo ./docs/install-003-pdns-recursor.sh

4. Sign in

Open http://127.0.0.1:9191/login with the credentials the installer printed (default admin / adminpass — change them in the install script before re-running, or via the admin UI).

Production

For a public deployment, terminate TLS at nginx and proxy to :9191. See docs/wiki/web-server/Running-PowerDNS-Admin-with-Systemd-Gunicorn-and-Nginx.md — the gunicorn launch command targets pdnsadmin:create_app() (not upstream's powerdnsadmin).

Tracks the latest Debian

Primary target is Debian 13 (trixie) with Python 3.13. Older releases should still work but aren't part of CI.

✅ Debian 13 (trixie)
✅ Python 3.13
✅ PowerDNS Auth 4.x
✅ PowerDNS Auth 5.x
✅ SQLite, MySQL, PostgreSQL
⌛ Debian 12 / Ubuntu 22.04 (best-effort)

Ready to manage your PowerDNS deployment?

Clone the repository, run the install scripts, and have a working PowerDNS + PowerDNS-Admin stack on your bare-metal box in minutes.

Standing on shoulders

Upstream: PowerDNS-Admin/PowerDNS-Admin — the original project. All the hard work on the zone editor, the Knockout zone-record table, the OAuth/SAML/LDAP backends, and the JSON API came from there. This fork is downstream cleanup, URL polish, and operability changes; the underlying product is still PowerDNS-Admin and full credit goes to that project.

This fork: github.com/kynoci/powerdns-admin

License: MIT — same as upstream.