Networking Azure

Poweradmin DNS Control Panel on Ubuntu 24.04 on Azure User Guide

| Product: Poweradmin 4.3.4 DNS Control Panel on Ubuntu 24.04 LTS on Azure

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 the gmysql database 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:8081 and 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 and dig resolves 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

All four services report active, PowerDNS Authoritative Server 5.1 and PHP 8.3 report their versions, and ss shows the control panel on port 80 and DNS on port 53 on all interfaces while the PowerDNS API on 8081 and MariaDB on 3306 are bound to 127.0.0.1 only

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.

The Poweradmin sign in page with the username and password fields and a language selector

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.

The Poweradmin dashboard showing Welcome Administrator, counts of 1 zone, 5 records, 1 user and 5 groups, and the PowerDNS tile reporting Online alongside tiles for search, forward zones, reverse zones, templates and supermasters

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)"

The credentials file listing proving mode 600 owned by root root, then the real login form rejecting admin/admin, admin/password, admin/poweradmin, admin/123456 and a blank password, the PowerDNS API returning HTTP 401 for a wrong key, and the API bound to 127.0.0.1 port 8081

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.

The forward zones list showing example.com as a MASTER zone with 5 records, with buttons to add a master zone or a slave zone and per zone actions for PTR, edit and delete

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 Poweradmin zone editor for example.com showing the add new record form and the record table populated with the SOA record, the NS record pointing at ns1.example.com, and the A record 203.0.113.10, each with a TTL of 3600 and inline edit and delete actions

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

The records table from the powerdns database listing the SOA, NS and A records for example.com, and dig returning the same SOA, the A record 203.0.113.10 for www.example.com, and the NS record, answered live by PowerDNS on port 53

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

The systemd drop in for nginx showing ConditionPathExists on the cloudimg poweradmin bootstrap ready marker, the same condition on pdns and php8.3-fpm, the marker and first boot sentinel present in /var/lib/cloudimg, and all three units reported as enabled so they survive a reboot

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 mysqldump of the powerdns database 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.