Skip to content
DevOps

DNS Admin UI: Manage PowerDNS Auth Server and Recursor in One Web Interface

Stop juggling API calls and config files. Manage zones, DNSSEC, forwarders, and cache from one place.

Dzmitry PadhrushaMarch 16, 202612 min read

Managing DNS infrastructure shouldn't require memorizing API endpoints or editing configuration files by hand. If your organization runs PowerDNS — whether for authoritative serving, recursive resolution, or both — you know the pain: scattered tools, cryptic API calls, zero visibility into who changed what, and onboarding new team members means handing them curl commands and a prayer.

At Krafteq, we needed a simple way to manage our internal DNS — both authoritative and recursive. After evaluating the existing tools and finding nothing that covered the full picture, we built DNS Admin UI. It's an open-source web application that gives your team a single, intuitive interface to manage both PowerDNS Authoritative Server and PowerDNS Recursor through their REST APIs.

The Problem

PowerDNS is one of the most powerful and flexible DNS platforms available. It exposes rich REST APIs for managing zones, records, DNSSEC, caching, forwarding, and more. But those APIs are designed for automation, not for humans sitting at a keyboard.

Here is what day-to-day DNS management typically looks like without a dedicated UI:

  • šŸ”§ Zone and record management means writing JSON payloads and sending them via curl or Postman. One typo in a fully qualified domain name — or one missing trailing dot — and you have a broken zone.

  • šŸ” DNSSEC operations — enabling, disabling, rotating keys — require multiple API calls and careful coordination.

  • āš™ļø Recursor configuration (forwarders, ACLs, cache control) lives in config files or separate API endpoints with their own quirks.

  • šŸ•µļø No audit trail. When something breaks at 2 AM, good luck figuring out who changed what. (It was probably you.)

  • šŸ”‘ Access control is all-or-nothing. Either someone has the API key, or they don't. There is no concept of read-only access or role-based permissions.

  • šŸ“š Onboarding is painful. Every new team member needs to learn the API, understand the naming conventions (trailing dots, anyone? Anyone? No?), and set up their own tooling.

These problems compound as teams grow. What works for a single admin managing a handful of zones becomes unmanageable at scale.

Existing Tools and the Gap They Leave

Several open-source web interfaces for PowerDNS already exist. The most notable are:

  • PowerDNS-Admin — the most popular option. A Python/Flask application that communicates through the PowerDNS REST API. It offers zone and record management, zone templates, DynDNS 2 support, statistics monitoring, and strong authentication options (LDAP, SAML, OAuth, 2FA).

  • Poweradmin — the longest-standing project. A PHP application that accesses the PowerDNS database directly for most operations and uses the REST API only for DNSSEC. It covers zones, records, DNSSEC, and supermaster configuration.

  • PDNSManager — a lightweight PHP interface that also writes directly to the PowerDNS MySQL database. Useful for simple setups and programmatic updates (e.g. Let's Encrypt dns-01 challenges), but limited in scope.

These tools solve the authoritative server side of the problem well. However, they all share the same blind spot: none of them manage the PowerDNS Recursor. If your infrastructure includes a recursor — for forwarding, caching, or recursive resolution — you are back to API calls, config files, and whispering sweet nothings to rec_control.

The key differentiator: DNS Admin UI is the only open-source web interface that manages both the PowerDNS Auth Server and the Recursor from a single dashboard.

DNS Admin UI was built to close this gap — a single interface for both the authoritative server and the recursor, communicating exclusively through their REST APIs.

What DNS Admin UI Does

Authoritative Server Management

The core of the application is zone and record management for the PowerDNS Authoritative Server:

  • šŸ“ Zone lifecycle — Create, edit, delete zones. Trigger AXFR zone transfers, send NOTIFY to secondaries, rectify zones, and export zone files.

  • āœļø DNS record editing — Full RRSet editing with a form-based interface. The UI automatically handles FQDN construction — type www and the zone suffix is appended for you. No more mysterious "Name is out of zone" errors that make you question your life choices.

  • šŸ” DNSSEC — Enable or disable DNSSEC per zone, view and manage cryptographic keys, all from a single panel.

  • šŸ”‘ TSIG keys — Create and manage Transaction Signature keys for secure zone transfers.

  • šŸ–„ļø Autoprimaries — Configure trusted primary servers for automatic zone provisioning.

  • šŸ” Search — Full-text search across all zones and records. Find that MX record you know exists somewhere without manually browsing every zone.

Recursor Management

For environments running PowerDNS Recursor alongside or independently of the authoritative server:

  • ā†—ļø Forwarder zones — Create and manage forwarding rules to direct queries for specific domains to designated upstream resolvers.

  • šŸ—„ļø Cache control — View cache statistics (both record cache and packet cache hits/misses) and flush caches selectively or globally.

  • šŸ›”ļø Configuration — Manage allow-from and allow-notify-from ACLs through the UI.

  • šŸ“Š RPZ statistics — Monitor Response Policy Zone activity.

Dashboard and Monitoring

A central dashboard provides at-a-glance visibility into both servers: zone counts, query statistics, cache hit ratios, and server health. No need to poll separate API endpoints to understand what is happening.

Security and Access Control

  • šŸ‘„ Role-based access — Two roles: admin (full control) and viewer (read-only). Admins manage zones and records; viewers can browse and search without risk of accidental changes.

  • šŸ”‘ Local authentication — Built-in username/password login with bcrypt-hashed passwords and JWT tokens in httpOnly cookies.

  • šŸŒ SSO / OIDC integration — Connect to Keycloak, Azure AD, Google, Okta, or any OpenID Connect provider. Roles are automatically synced from the identity provider on each login.

  • šŸ“‹ Audit log — Every mutation is logged with who did it, what changed, and when. Searchable and filterable. This is the first place to look when troubleshooting DNS issues.

Getting Started

DNS Admin UI ships as a single Docker image that bundles both the backend API and the frontend. The quickest way to get everything running — including PowerDNS itself — is with a single Docker Compose file.

Prerequisites

You need Docker with the Compose plugin installed on the host machine. That is it.

Windows users: We recommend running from inside WSL. Docker bind mounts don't work reliably with Windows-style paths.

Quick Start: All-in-One Setup

This setup starts the PowerDNS Authoritative Server, PowerDNS Recursor, and DNS Admin UI together on a shared network. Create the following file structure:

dns-admin/
ā”œā”€ā”€ docker-compose.yml
ā”œā”€ā”€ pdns.conf
└── recursor.yml

pdns.conf

# PowerDNS Authoritative Server configuration# SQLite backend — lightweight, no external DB server neededlaunch=gsqlite3                          # Use the SQLite3 backend modulegsqlite3-database=/var/lib/powerdns/pdns.sqlite3  # Path to the SQLite database filegsqlite3-pragma-synchronous=normal       # Faster writes; "full" is safer but slower# REST API — required for DNS Admin UI to manage zones and recordsapi=yes                                  # Enable the HTTP REST APIapi-key=changeme                         # Shared secret — must match PDNS_API_KEY in docker-compose.ymlwebserver=yes                            # Enable the built-in HTTP server (serves the API)webserver-address=0.0.0.0                # Listen on all interfaces inside the containerwebserver-port=8081                      # HTTP port for the API (default: 8081)webserver-allow-from=0.0.0.0/0,::/0      # Allow API access from any IP (containers use internal Docker IPs)# DNS listenerlocal-address=0.0.0.0                   # Listen for DNS queries on all interfaceslocal-port=53                            # Standard DNS port# Loggingloglevel=4                               # 0=emergency … 4=info … 7=debug (4 is good for dev)log-dns-queries=yes                      # Log every incoming DNS query (disable in production for performance)

āš ļø Why 0.0.0.0/0 for webserver-allow-from? Inside Docker, containers communicate over an internal bridge network using private IPs (e.g. 172.18.0.x). Setting 127.0.0.1 would block DNS Admin UI from reaching the API. This is safe because the API port is not published to the host — only containers on the same Docker network can reach it. In production, restrict this to the specific subnet or IP of the DNS Admin UI container.

recursor.yml

PowerDNS Recursor v5.1+ requires YAML configuration format.

# DNS listener — accepts recursive queries from clientsincoming:  listen:    - 0.0.0.0:53          # Listen on all interfaces, standard DNS port  allow_from:              # IP ranges allowed to send DNS queries    - 0.0.0.0/0            # Allow all IPv4 (restrict to your client subnets in production!)    - ::/0                 # Allow all IPv6 (restrict in production!)# REST API — required for DNS Admin UI to manage forwarders, cache, and ACLswebservice:  webserver: true          # Enable the built-in HTTP server (serves the API)  api_key: changeme        # Shared secret — must match RECURSOR_API_KEY in docker-compose.yml  address: 0.0.0.0         # Listen on all interfaces inside the container  port: 8082               # HTTP port for the API (default: 8082)  allow_from:              # IP ranges allowed to access the API    - 0.0.0.0/0            # Allow from any IP (required for Docker networking, see note above)    - ::/0# Logginglogging:  loglevel: 4              # 0=emergency … 4=info … 7=debug (4 is good for dev)

docker-compose.yml

services:  # --- PowerDNS Authoritative Server ---  pdns-auth:    image: powerdns/pdns-auth-50:latest    volumes:      - ./pdns.conf:/etc/powerdns/pdns.conf:ro    ports:      - "8081:8081"                      # API (optional — for debugging)      - "5300:53/udp"                    # DNS on host port 5300 (avoids conflict with port 53)      - "5300:53/tcp"    networks:      - dns-net    healthcheck:      test: ["CMD", "pdns_control", "rping"]      interval: 10s      timeout: 5s      retries: 3  # --- PowerDNS Recursor ---  pdns-recursor:    image: powerdns/pdns-recursor-52:latest    volumes:      - ./recursor.yml:/etc/powerdns/recursor.yml:ro    command: --config-dir=/etc/powerdns --api-config-dir=/etc/powerdns/api.d    ports:      - "8082:8082"                      # API (optional — for debugging)      - "5301:53/udp"                    # DNS on host port 5301      - "5301:53/tcp"    networks:      - dns-net    healthcheck:      test: ["CMD", "rec_control", "ping"]      interval: 10s      timeout: 5s      retries: 3  # --- DNS Admin UI ---  dns-admin-ui:    image: krafteq.azurecr.io/dns-admin-ui:latest    ports:      - "3000:3000"    environment:      PDNS_URL: http://pdns-auth:8081      PDNS_API_KEY: changeme      RECURSOR_URL: http://pdns-recursor:8082      RECURSOR_API_KEY: changeme      JWT_SECRET: change-me-to-a-long-random-string    volumes:      - dns-admin-data:/app/apps/backend/data    networks:      - dns-net    depends_on:      pdns-auth:        condition: service_healthy      pdns-recursor:        condition: service_healthy    restart: unless-stoppednetworks:  dns-net:    driver: bridgevolumes:  dns-admin-data:

šŸ“Œ Note on --api-config-dir: The recursor requires this setting to allow creating and deleting forwarder zones via the API. It has no YAML equivalent in Recursor v5.2, so it is passed as a command-line argument. The directory /etc/powerdns/api.d is created automatically by the recursor on startup.

Start everything

docker compose up -d

On first start, Docker builds the PowerDNS images, and DNS Admin UI automatically runs database migrations and creates a default admin user. The depends_on health checks ensure PowerDNS is ready before the UI starts.

Log in

Open http://localhost:3000 in your browser. Log in with the default credentials:

  • Username: admin

  • Password: admin

āš ļø Change the password immediately after first login. Yes, we know you won't. Do it anyway.

Verify connectivity

Navigate to the Dashboard page. If everything is configured correctly, you will see server statistics, zone counts, and cache metrics for both the authoritative server and the recursor.

If the dashboard shows connection errors, check that:

  • All three containers are running: docker compose ps

  • PowerDNS containers are healthy: docker compose ps should show (healthy) status

  • API keys match between docker-compose.yml and the PowerDNS config files

  • Containers are on the same network: docker network inspect dns-admin_dns-net

Already Running PowerDNS?

If you already have PowerDNS instances running, you can run DNS Admin UI standalone and point it at your existing servers. Make sure the REST API is enabled:

  • Authoritative Server: api=yes, api-key=<secret>, webserver=yes in pdns.conf

  • Recursor: webservice.webserver: true, webservice.api_key: <secret> in recursor.yml

Then start DNS Admin UI with a minimal docker-compose.yml:

services:  dns-admin-ui:    image: krafteq.azurecr.io/dns-admin-ui:latest    ports:      - "3000:3000"                      # Web UI and API    environment:      PDNS_URL: http://your-auth-host:8081       # Replace with your auth server's address      PDNS_API_KEY: your-auth-api-key            # Must match your auth server's api-key      RECURSOR_URL: http://your-recursor:8082    # Replace with your recursor's address      RECURSOR_API_KEY: your-recursor-api-key    # Must match your recursor's webservice.api_key      JWT_SECRET: change-me-to-a-long-random-string  # Use a strong random value    volumes:      - dns-admin-data:/app/apps/backend/data    # Persist SQLite DB across restarts    restart: unless-stoppedvolumes:  dns-admin-data:

Ensure that webserver-allow-from (auth server) and webservice.allow_from (recursor) include the IP address of the machine running DNS Admin UI. The default localhost-only ACLs will reject connections from external hosts.

Setting Up SSO

DNS Admin UI supports single sign-on via any OIDC-compliant identity provider — Keycloak, Azure AD, Google, Okta, and others. The setup boils down to:

  1. Configure your identity provider — create a client (confidential, with a secret), set the redirect URI to http://<your-host>:3000/auth/oidc/callback, and add a role mapper so that user roles appear in the ID token

  2. Set the OIDC environment variables on the dns-admin-ui container:

  dns-admin-ui:    environment:      # ... existing PDNS_URL, PDNS_API_KEY, RECURSOR_URL, RECURSOR_API_KEY, JWT_SECRET ...      OIDC_ISSUER_URL: https://your-idp/realms/your-realm   # OIDC discovery URL      OIDC_CLIENT_ID: dns-admin-ui                           # Client ID from your IdP      OIDC_CLIENT_SECRET: your-client-secret                 # Client secret from your IdP      OIDC_REDIRECT_URI: http://localhost:3000/auth/oidc/callback  # Must match the redirect URI in your IdP
  1. Restart and a "Sign in with SSO" button appears on the login page. Local login remains available as a fallback.

Roles are mapped automatically: the backend reads the roles claim from the ID token (configurable via OIDC_ROLES_CLAIM) and grants admin access if it contains admin (configurable via OIDC_ADMIN_ROLE). Users are auto-created on first SSO login with viewer role by default.

For a complete step-by-step walkthrough using Keycloak — including running Keycloak in Docker, creating a realm, configuring roles, and setting up the role mapper — see the Keycloak setup guide.

Running Behind a Reverse Proxy

For production deployments, place DNS Admin UI behind a reverse proxy for TLS termination. The app serves both the API and frontend from a single port, so configuration is straightforward:

server {    listen 443 ssl;    server_name dns-admin.example.com;    ssl_certificate /etc/ssl/certs/dns-admin.crt;    ssl_certificate_key /etc/ssl/private/dns-admin.key;    location / {        proxy_pass http://127.0.0.1:3000;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;    }}

Data Persistence

The application stores its data (users, audit logs, settings) in a SQLite database at /app/apps/backend/data/dns-admin.db inside the container. Mount a Docker volume to persist it across container restarts and upgrades:

volumes:  - dns-admin-data:/app/apps/backend/data

DNS zones and records are stored in PowerDNS itself — the DNS Admin UI database only holds application-level data.

Wrapping Up

DNS Admin UI bridges the gap between PowerDNS's powerful APIs and the day-to-day reality of managing DNS infrastructure as a team. It gives you a visual interface for zone and record management, DNSSEC operations, recursor configuration, and cache control — all backed by role-based access and a full audit trail.

If you are managing PowerDNS and tired of curl commands, tribal knowledge, and 2 AM "who touched DNS?" mysteries, give it a try:

docker pull krafteq.azurecr.io/dns-admin-ui:latest

The project is open source and available on GitHub. We at Krafteq also provide DevOps and infrastructure services — from CI/CD pipelines and cloud infrastructure to SRE enablement and production support. If your team needs help with DNS, infrastructure automation, or anything in between, get in touch.