Poweradmin DNS Control Panel on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and configuration of Poweradmin on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Poweradmin is an open source, web based DNS control panel for PowerDNS, developed by the Poweradmin Development Team and published at poweradmin.org. It gives you a browser interface for the work that would otherwise mean editing zone files or writing SQL: creating forward and reverse zones, adding and editing records, applying zone templates, running bulk operations, and delegating zone administration to other people.
The image installs Poweradmin 4.3.4 from the upstream release, PowerDNS Authoritative Server 5.1 from the official repo.powerdns.com packages, and MariaDB from Ubuntu 24.04, and wires all three together. Poweradmin and PowerDNS share one database, so a record you add in the panel is served by the name server straight away rather than after a reload. Unattended security upgrades are configured to keep the server patched on your running VM.
One appliance, three services. nginx and php8.3-fpm serve the control panel on port 80, pdns answers DNS on port 53 over both UDP and TCP on all interfaces, and mariadb holds both the PowerDNS zone data and the Poweradmin panel tables. The PowerDNS REST API (127.0.0.1:8081) and MariaDB (127.0.0.1:3306) are bound to loopback only and are never exposed to the network.
Security by design — there is no administrator account in the image. Rather than shipping a default login and rotating it, this image ships no Poweradmin account at all. On the very first boot of every VM a one shot service generates a unique administrator password, unique database passwords for both services, a unique PowerDNS API key and a unique session key, creates the single administrator account with a bcrypt password hash, provisions a demonstration zone, and then proves the new password signs in through the real login form and that admin/admin, a blank password and other common guesses do not, before writing /root/poweradmin-credentials.txt (mode 0600, root only).
The panel cannot serve an unprovisioned instance. The control panel, the PHP runtime and the name server are each gated on a bootstrap marker that first boot writes only after every credential is in place. Until that marker exists systemd skips those units entirely, so there is no window in which a half provisioned appliance is reachable. The units are still enabled, so the appliance comes straight back after a reboot.
What is included:
-
Poweradmin 4.3.4 served by nginx and PHP 8.3 FPM, with the upstream web installer removed from the deployed tree so the setup wizard can never be reached
-
PowerDNS Authoritative Server 5.1 (
pdns.service) answering DNS on port 53, backed by thegmysqldatabase backend -
MariaDB (
mariadb.service) holding the PowerDNS zone data and the Poweradmin panel tables in one database, bound to loopback -
The PowerDNS REST API bound to
127.0.0.1:8081and authenticated with a per instance key, consumed by the panel for server status and DNSSEC operations -
One demonstration zone (
example.com) so the panel has real records to show anddigresolves out of the box, ready for you to replace with your own domain -
A per instance administrator password, database passwords and DNS API key generated on first boot and documented in
/root/poweradmin-credentials.txt(0600) -
Permission templates and user groups for delegated administration, an audit log of user and zone changes, and multi factor authentication for panel accounts
Prerequisites
-
Active Azure subscription, SSH public key, VNet and subnet in the target region
-
Subscription to the Poweradmin listing on Azure Marketplace
-
Network Security Group rules allowing TCP 22 (administration), TCP 80 (the control panel) and both UDP and TCP 53 (DNS) from the networks that need them
-
A registered domain if you intend to serve public DNS, plus access to your registrar to set name server records
Step 1: Deploy from the Azure Portal
Search Poweradmin in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow TCP 80 for the control panel from your administrative networks, UDP 53 and TCP 53 for DNS from the clients and resolvers that will query the server, and TCP 22 for administration. DNS uses UDP 53 for most queries and falls back to TCP 53 for large responses and zone transfers, so open both. The PowerDNS REST API and the database stay on loopback and are never exposed.
Step 2: Deploy from the Azure CLI
RG="dns-prod"; LOCATION="eastus"; VM_NAME="ns1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/poweradmin-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 53 --priority 1002
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1003
Step 3: First boot and your credentials
On first boot the image mints every per instance secret, creates the administrator account, provisions the demonstration zone, opens the bootstrap gate, starts the panel and the name server, verifies the new credentials work and the common defaults are rejected, and writes /root/poweradmin-credentials.txt. This completes within a minute or two. SSH in as azureuser and read the details:
sudo cat /root/poweradmin-credentials.txt
The file is mode 0600 and owned by root, so only a privileged user can read it. It contains the panel URL, the administrator username and password, both database passwords and the PowerDNS API key.
Step 4: Confirm the appliance is running
All four services should report active. ss confirms the control panel is on port 80 and DNS on port 53 across all interfaces, while the PowerDNS API and MariaDB are bound to loopback only.
systemctl is-active mariadb.service pdns.service php8.3-fpm.service nginx.service
pdns_server --version 2>&1 | grep -oE 'PowerDNS Authoritative Server [0-9.]+' | head -1
php -r 'echo "PHP ".PHP_VERSION."\n";'
ss -tulnp | grep -E ':(80|53|8081|3306) ' | sed 's/users:.*//' | sort

Step 5: Sign in to the control panel
Browse to http://<your-vm-public-ip>/ and sign in with the username admin and the password from the credentials file. Poweradmin derives its own base URL from the address you reach it on, so no configuration is needed for the panel to work on your VM's public IP or behind a DNS name you point at it.

After signing in the dashboard shows live counts of zones, records, users and groups, with tiles for zone management, zone operations and administration. The PowerDNS tile reports Online, which confirms the panel is talking to the name server over the loopback REST API with the per instance key.

You can prove the same sign in from the command line. This uses the per instance password from the credentials file to complete a real login through the form, then checks that the common default passwords are refused:
sudo /usr/local/sbin/poweradmin-login-check.sh admin '<POWERADMIN_ADMIN_PASSWORD>' && echo "per-VM password: ACCEPTED (correct)"
sudo /usr/local/sbin/poweradmin-login-check.sh admin 'admin' || echo "admin/admin: REJECTED (correct)"
sudo /usr/local/sbin/poweradmin-login-check.sh admin '' || echo "blank password: REJECTED (correct)"

Step 6: Change the administrator password
The first thing to do after signing in is set your own password. In the panel open the Account menu in the top right and choose Password, or browse to /password/change. Enter the per instance password from the credentials file as the current password and choose a new one.
Poweradmin stores passwords as bcrypt hashes at cost 12, so the new password is never recoverable from the database. Once you have changed it, the copy in /root/poweradmin-credentials.txt is stale — keep the file for the database passwords and API key, or remove the administrator password line from it.
Step 7: Browse the demonstration zone and its records
Open Zones then Forward zones. The image ships one demonstration zone, example.com, as a MASTER zone with five records, so the panel has real data to show from the moment you sign in.

Click the zone to open the record editor. This is the heart of the product: every record in the zone is listed with its name, type, content, priority and TTL, each editable in place, with an Add new record form above it and multi record and bulk add modes for larger changes.

The demonstration records use 203.0.113.10, an address reserved for documentation, which you replace with your own.
Step 8: Prove a record you manage is answered on port 53
Poweradmin writes directly into the same database PowerDNS reads, and the image disables the PowerDNS zone cache refresh interval, so a change in the panel is served immediately. Query the name server directly to see the same records the panel showed you:
sudo mysql -t powerdns -e "SELECT name, type, content, ttl FROM records ORDER BY type"
dig @127.0.0.1 example.com SOA +noall +answer
dig @127.0.0.1 www.example.com A +noall +answer
dig @127.0.0.1 example.com NS +short

To confirm from a client machine rather than the VM itself, query the public IP: dig @<your-vm-public-ip> www.example.com. The aa flag in the answer header confirms an authoritative answer.
Step 9: Add your own zone
In the panel choose Zones then Add master zone, enter your domain, and Poweradmin creates the zone with an SOA and the name server records from its configured defaults. Add an A record for the apex and for www pointing at your service address, then verify with dig.
The equivalent from the command line, if you prefer to script the initial load, uses the PowerDNS tooling directly. Both routes write to the same database, so a zone created either way appears in the panel:
sudo pdnsutil zone create <your-domain>
sudo pdnsutil rrset add <your-domain> @ A 3600 <your-service-ip>
sudo pdnsutil rrset add <your-domain> www A 3600 <your-service-ip>
sudo pdnsutil zone list <your-domain>
Substitute your own domain and service address for the placeholders. To inspect the zone that already exists instead, the same commands work against the demonstration zone:
sudo pdnsutil zone list example.com
sudo pdnsutil zone show example.com | head -12
Once you have your own zone in place you can delete the demonstration zone from the panel with the delete action in the forward zone list.
Step 10: Delegate zone administration
Poweradmin's permission templates let you hand out zone administration without handing over the whole server. Open Users then Add user, and assign one of the shipped templates:
- Administrator — full rights over every zone, user and setting
- Zone Manager — full management of their own zones, including creation, editing, deletion and templates
- Editor — edit records in their own zones, but cannot change SOA or NS records
- Viewer — read only access to their own zones, with search
- Guest — no permissions, for accounts awaiting approval
Group templates with the same names exist for Groups, so you can grant access to a team rather than per person. Zone ownership is assigned per zone from the zone's Ownership button in the editor. Every user and zone change is written to the audit log, which you can review under the zone and user logs.
Step 11: How the first boot gate protects an unprovisioned instance
This appliance runs three services that all persist state, and all three are enabled so they survive a reboot. To make sure none of them can ever serve an instance whose credentials have not been generated, each carries a systemd condition on a bootstrap marker that first boot writes only after every secret is in place:
grep -h ConditionPathExists /etc/systemd/system/{pdns,php8.3-fpm,nginx}.service.d/cloudimg-bootstrap-gate.conf
ls -l /var/lib/cloudimg/
systemctl is-enabled pdns.service php8.3-fpm.service nginx.service

Ordering directives alone would not be enough: After= and Requires= control the order units start in, but they still start a unit if the first boot service is slow or fails. The condition makes systemd skip the unit entirely instead. If you ever need to take the appliance out of service deliberately, removing the marker and restarting will leave the panel and the name server stopped until you put it back.
Step 12: Enable DNSSEC
DNSSEC signing is performed through the PowerDNS REST API, which the panel is already configured to use over loopback with the per instance key. Open a zone in the panel and use the DNSSEC action to add a key and view the DS and DNSKEY records to hand to your registrar.
From the command line the equivalent is:
sudo pdnsutil zone show example.com | head -20
To sign a zone and read back the DS records for your registrar, use pdnsutil secure-zone followed by pdnsutil show-zone on your own domain once it is in place.
Step 13: Delegate your domain at your registrar
To serve public DNS for your domain, set your registrar's name server records to point at this instance. You will normally want at least two name servers for redundancy, which means either a second instance of this image configured as a slave zone, or a third party secondary DNS provider fed by zone transfer.
Set the name server names in the panel's zone records, then at your registrar set the delegation to those names and provide glue records with this instance's public IP. Allow up to 48 hours for the change to propagate through the DNS hierarchy.
Step 14: Security recommendations
-
Change the administrator password immediately after first sign in, and enable multi factor authentication for panel accounts under the Account menu.
-
Restrict TCP 80 to your administrative networks in the Network Security Group. The control panel is an administrative interface and does not need to be reachable from the internet, whereas port 53 does.
-
Put TLS in front of the panel before exposing it beyond a trusted network. Terminate HTTPS with a certificate for a name you control, either on this instance or on an Azure Application Gateway or Load Balancer in front of it, so panel credentials are never sent in clear text.
-
Keep the API and the database on loopback. The PowerDNS REST API (
127.0.0.1:8081) and MariaDB (127.0.0.1:3306) are bound to loopback in the shipped configuration. There is no reason to change that on a single instance appliance. -
Use permission templates rather than shared administrator accounts so each person's changes are attributable in the audit log.
-
Back up the database, which holds both your zone data and the panel's users and permissions. A
mysqldumpof thepowerdnsdatabase captures everything. -
Keep unattended security upgrades enabled, which the image configures by default.
Step 15: Support and licensing
Poweradmin is distributed under the GNU General Public License version 3. PowerDNS Authoritative Server is distributed under the GNU General Public License version 2 with an OpenSSL linking exception, and MariaDB under the GNU General Public License version 2. This image bundles all three unmodified; the licence text for Poweradmin ships at /var/www/poweradmin/LICENSE on the instance.
cloudimg provides 24/7 technical support for this image by email at support@cloudimg.co.uk and by live chat, with a one hour average response time for critical issues. We help with deployment and first boot configuration, migrating existing zones into the panel, managing forward and reverse zones and records, user accounts and permission templates for delegated administration, multi factor authentication, DNSSEC signing, zone transfers to secondary name servers, delegating your domain at your registrar, REST API automation, Poweradmin and PowerDNS version upgrades, and MariaDB administration.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.