A modern, secure, and feature-rich Web Management Interface for PowerDNS, enhanced with advanced security hardening, Role-Based Access Control (RBAC), multi-backend authentication, dynamic zone templating, Python 3.12+/3.13 compatibility, and automated database migration idempotency — maintained by @alsyundawy.
| Category | Features |
|---|---|
| 🌐 Zone Management | Forward & Reverse DNS (IPv4/IPv6 PTR), Zone Templating, IDN/Punycode, DNSSEC Management |
| 🔐 Authentication | Local, SAML 2.0, LDAP (OpenLDAP/Active Directory), OAuth2 (Google, GitHub, Azure, OpenID) |
| 🛡️ Security | TOTP 2FA with Replay Protection, RBAC, API Key Isolation, CSRF Protection, SSRF Prevention |
| 📊 Monitoring | Real-time PowerDNS Stats, Activity Logging, Audit Trail, Zone Change History |
| ⚡ Automation | RESTful API for Zone/Record Automation, DynDNS2 Protocol, Docker & Compose Ready |
| 🐍 Compatibility | Python 3.10–3.13, Flask 3.x, SQLAlchemy 1.4+, PostgreSQL / MySQL / SQLite |
docker run -d \
--name powerdns-admin \
-e SECRET_KEY='replace-with-a-long-secure-random-key' \
-v pda-data:/data \
-p 9191:80 \
alsyundawy/powerdns-admin:latest
Access the interface at http://localhost:9191.
git clone https://github.com/alsyundawy/PowerDNS-Admin.git
cd PowerDNS-Admin
docker-compose up -d
PowerDNS-Admin supports configuration via environment variables or custom config files (docker_config.py / config.py):
| Variable | Description | Default |
|---|---|---|
SECRET_KEY |
Secret key for session encryption | (Required) |
SQLALCHEMY_DATABASE_URI |
Database connection URI | sqlite:////data/pdns.db |
PDNS_STATS_URL |
PowerDNS API endpoint URL | http://127.0.0.1:8081 |
PDNS_API_KEY |
PowerDNS API Key | "" |
CAPTCHA_ENABLE |
Enable CAPTCHA on registration page | True |

Comprehensive maintenance, security hardening, database migration idempotency, UI/UX redesign, and Python 3.12+/3.13 compatibility — built on top of
0.4.2-alsyundawy-fix.
verify = False with Setting().get('verify_ssl_connections') in lib/helper.py.otp_last_used; prevents replay attacks.api_current_user (LocalProxy) ensures session cookies cannot override API Basic Auth.403).HTTP 502 surfaced).@operator_role_required guard on /template/<template>/apply.Role.get_id_by_name(name) auto-seeds default roles on empty databases.787bdba9e147_init_db.py checks table existence before CREATE TABLE; env.py auto-stamps alembic_version to head.SESSION_SQLALCHEMY = models.db bound before Session(app); Sessions uses extend_existing = True.authenticate_user() to redirect to dashboard.dashboard on success.CAPTCHA_ENABLE = False.inject_pdns_version registered globally; prevents TypeError on dashboard sub-menus.Version 0.4.3 Modified By Alsyundawy.fetch_remote no longer drops caller-supplied headers (e.g., X-API-Key).isinstance(jdata, dict) guard added in models/domain.py.ascii_lowercase, ascii_uppercase, and punctuation.<input type="hidden" id="auth_method_hidden"> replaces duplicate controls; JS syncs the dropdown.#ffffff with rgba(239,68,68,0.20) background (contrast ≥ 4.5:1).safeSrc() Linter Compliance — void urlErr; added in catch block; screen-reader labels and honeypot field included.distutils and deprecated imghdr with modern alternatives..github/workflows/jekyll-gh-pages.yml for automated GitHub Pages deployment.Frontend security and template hardening. Commit: bcbb766.
safeSrc logo URL validation improvements; CSP nonce on register.html; redirect URL scheme validation.Comprehensive security & CodeQL remediation release. Commit: 789c185.
cryptography → 50.0.0, pyasn1 → 0.6.4, setuptools → 83.0.0.SQLAlchemy 1.4 upgrade (postgresql:// URI required), OAuth auto-config, case-insensitive user lookup.
| Resource | Link |
|---|---|
| 📄 API Reference | docs/API.md |
| 🔑 OAuth Setup Guide | docs/oauth.md |
| 📋 Full Changelog | CHANGELOG.md |
| 📝 Technical Notes | docnote/changelog.md |
| 🤝 Contribution Guide | docs/CONTRIBUTING.md |
This project is licensed under the MIT License. Maintained with ❤️ by @alsyundawy.