PowerDNS management UI with a built-in API proxy for controlled automation
PowerDNS-UI is a modern, self-hosted control plane for PowerDNS Authoritative servers. It combines a clean web interface for DNS administration with a built-in PowerDNS-compatible API proxy for automation, ACME DNS-01 challenges, and delegated API access.
Built as a lightweight alternative to PowerDNS-Admin, it provides zone and record management, pending-change validation, change history, LDAP/local authentication, multi-server connections, and granular token-based API access without exposing your raw PowerDNS API directly.
Use it as:
- A day-to-day web UI for managing zones and records.
- A secure API gateway in front of PowerDNS for certbot, lego, external services, and internal automation.
docker run -d --name powerdns-ui -p 3000:3000 --restart unless-stopped ghcr.io/adminsyspro/powerdns-ui:latestThen open http://your-server:3000 — default credentials: admin / admin
| Feature | Description |
|---|---|
| PowerDNS API Proxy | Expose a controlled PowerDNS-compatible API without giving clients direct access to the PowerDNS backend |
| Granular API Access | Issue per-client tokens with zone-level permissions, record-level ACLs, regex rules, ACME shortcuts, and request logs |
| Zone Management | Create, edit, delete, and export DNS zones (Native, Master, Slave) |
| Record Editing | Full CRUD for all record types (A, AAAA, CNAME, MX, TXT, SRV, CAA, etc.) |
| Multi-Selection | Bulk delete, enable, and disable records and zones |
| Pending Changes | Review and validate changes before applying them to the server |
| Change History | Track all modifications with diff view and timeline |
| Global Search | Search across zones, records, and IPs |
| Zone Switcher | Quickly navigate between zones with instant search |
| BIND Zone Import | Import BIND zone files to create new zones or stage records into existing zones |
| Nameserver Pools | Configure reusable NS pools and apply them during zone creation |
| Record Export | Export records as text, CSV, or PDF |
| LDAP Authentication | Integrate with Active Directory / LDAP |
| Local Authentication | Built-in user management with bcrypt passwords |
| Multi-Server | Connect to multiple PowerDNS instances |
| DNSSEC Status | View DNSSEC status per zone |
| Real-Time Sync | Background sync with local SQLite cache for fast pagination |
| Dark Mode | Full dark/light theme support |
| Responsive | Works on desktop, tablet, and mobile |
PowerDNS-UI includes a built-in API proxy compatible with the PowerDNS Authoritative API. Each token can be limited to specific zones and record patterns, making it suitable for scoped automation and delegated DNS access.
This is useful for:
- ACME DNS-01 automation — allow certbot, lego, or other ACME clients to update only
_acme-challengeTXT records. - Delegated DNS management — give teams or services access to selected zones without full PowerDNS API credentials.
- Public/private separation — expose proxy endpoints publicly while keeping the admin UI and PowerDNS API on private networks.
- Auditing — review API requests, status codes, zones, client IPs, latency, and errors from the UI.
- Migration — import an existing
powerdns-api-proxyconfig and keep existing hashed tokens valid.
External clients authenticate with an API token via the X-API-Key header. Each token (called an API Access) defines which zones can be accessed and which records can be modified.
Client (certbot) → Nginx → PowerDNS-UI Proxy → PowerDNS API
↕
Token validation
Zone filtering
Record-level ACL
- Token-based authentication — SHA-512 hashed tokens, generated and displayed once
- Per-zone permissions — restrict which zones a token can read/write
- Record-level rules — allow specific records (exact match) or patterns (regex)
- ACME support — auto-allow
_acme-challenge.*TXT records for Let's Encrypt - Request logging — real-time logs with method, status, zone, IP, duration, and errors
- Config import — import existing
config.ymlfrom powerdns-api-proxy
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/servers/{id}/zones |
List zones (filtered by permissions) |
| GET | /api/v1/servers/{id}/zones/{zone} |
Get zone details (records filtered) |
| PATCH | /api/v1/servers/{id}/zones/{zone} |
Update records (validated against ACL) |
| PUT | /api/v1/servers/{id}/zones/{zone}/notify |
Notify zone |
| GET | /health/pdns |
Health check (no auth) |
| GET | /info/allowed |
List permissions for the calling token |
- In the UI, go to API Proxy and click Import to paste your existing
config.yml - Existing
token_sha512values are preserved — client tokens remain valid - Update your Nginx config to point to PowerDNS-UI (see below)
For security, expose only the proxy endpoints on the public-facing domain. The UI should be accessed through a separate vhost.
Proxy vhost (e.g., ssl.example.com — used by certbot and external clients):
server {
listen 443 ssl;
server_name ssl.example.com;
ssl_certificate /etc/letsencrypt/live/ssl.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ssl.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /api/v1/ {
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;
}
location /health/pdns {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
location /info/allowed {
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;
}
location / {
return 404;
}
}UI vhost (e.g., dns-admin.example.com — used by administrators):
server {
listen 443 ssl;
server_name dns-admin.example.com;
ssl_certificate /etc/ssl/certs/dns-admin.pem;
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;
}
}| Variable | Default | Description |
|---|---|---|
NODE_ENV |
production |
Node environment |
PORT |
3000 |
HTTP port |
HOSTNAME |
0.0.0.0 |
Listen address |
Server connections and LDAP settings are configured through the web UI at Settings.
server {
listen 443 ssl;
server_name dns.example.com;
ssl_certificate /etc/ssl/certs/dns.pem;
ssl_certificate_key /etc/ssl/private/dns.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;
}
}- Docker & Docker Compose
- PowerDNS Authoritative 4.x with API enabled
- Network access to PowerDNS API (default port 8081)
MIT — Free for personal and commercial use.

