PowerDNS Recursor on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and configuration of PowerDNS Recursor on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. PowerDNS Recursor is a high performance, standards compliant open source recursive DNS resolver developed by PowerDNS.COM BV. Unlike an authoritative server, which publishes the zones you own, a recursor resolves names on behalf of your clients: it walks the DNS hierarchy from the root servers down, follows delegations, validates DNSSEC signed answers, and caches results so repeat lookups are answered instantly.
The image installs PowerDNS Recursor 5.3 from the official PowerDNS packages (the repo.powerdns.com rec 53 stable branch), pinned above the distribution package. Unattended security upgrades are configured to keep the resolver patched on your running VM.
Recursive, not authoritative. This server resolves names for your clients; it does not publish zones. It is the resolver you point your workloads, containers and office networks at instead of a public resolver, keeping your DNS traffic private and under your control.
Never an open resolver — secure by default. An internet facing resolver that answers anyone is a DNS amplification hazard. This image ships with recursion restricted to loopback and the RFC1918 private ranges only (incoming.allow_from). Queries from arbitrary internet sources are refused, so this instance can never be abused as a reflector. Opening the resolver to your own client subnets is a single documented change (Step 8).
Security by design — no default credentials. The REST API key is the equivalent of an administrator password for the resolver, so this image never ships a fixed key. On the very first boot of every VM a fresh per instance REST API key and a fresh webserver password are generated, and the details are written to /root/powerdns-recursor-credentials.txt (mode 0600, root only). The REST API and status webserver are bound to 127.0.0.1 only, so the management surface is never exposed to the network while DNS resolution answers on port 53 for your allowed clients.
What is included:
-
PowerDNS Recursor 5.3 from the official PowerDNS packages, run under systemd as the unprivileged
pdnsuser (pdns-recursor.service) -
Recursion restricted to loopback and RFC1918 private ranges by default (
incoming.allow_from) so the instance is never an open resolver -
DNSSEC validation of signed answers, and the systemd-resolved stub listener disabled so the Recursor owns port 53 cleanly
-
The REST API enabled and bound to loopback (
127.0.0.1:8082), authenticated with a per instanceX-API-Key, plus the status webserver -
A per instance REST API key and webserver password generated on first boot, documented in
/root/powerdns-recursor-credentials.txt(0600) -
YAML settings (PowerDNS Recursor 5.x native format) with the cloudimg configuration split into a base drop-in and a per VM secrets drop-in under
/etc/powerdns/recursor.d/
Prerequisites
-
Active Azure subscription, SSH public key, VNet + subnet in target region
-
Subscription to the PowerDNS Recursor listing on Azure Marketplace
-
Network Security Group rules allowing TCP 22 (admin) and both UDP and TCP 53 (DNS) from the client networks that will use the resolver
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for a small resolver. Resolvers serving heavy query volumes should use Standard_D2s_v5 or larger.
Step 1: Deploy from the Azure Portal
Search PowerDNS Recursor in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow UDP 53 and TCP 53 (DNS) from your client networks, and TCP 22 for administration. DNS uses UDP 53 for most queries and falls back to TCP 53 for large responses, so open both. The REST API stays on loopback and is never exposed.
Step 2: Deploy from the Azure CLI
RG="dns-prod"; LOCATION="eastus"; VM_NAME="resolver1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/powerdns-recursor-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 53 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002
Step 3: First boot
On first boot the image generates a fresh per instance REST API key and webserver password, starts pdns-recursor, verifies the API key round trips and a real recursive query resolves, and writes /root/powerdns-recursor-credentials.txt. This completes within a minute. SSH in as azureuser and read the details:
sudo cat /root/powerdns-recursor-credentials.txt
Step 4: Confirm the service is running
pdns-recursor.service (the resolver daemon) is active. ss confirms DNS is listening on :53 (UDP and TCP, all interfaces) while the REST API is bound to 127.0.0.1:8082 only.
systemctl is-active pdns-recursor.service
pdns_recursor --version 2>&1 | head -1
ss -tlnup | grep -E ':53 |:8082 '

Step 5: Resolve a name
The resolver answers recursive queries for allowed clients. Loopback is allowed by default, so a lookup works immediately on the VM. Because the Recursor caches answers, a repeated query is served instantly from cache.
dig @127.0.0.1 A example.com +noall +answer
dig @127.0.0.1 AAAA cloudflare.com +short
dig @127.0.0.1 MX gmail.com +short

Step 6: Use the REST API
The REST API exposes metrics and cache management and is the same interface automation tools use. Read your per instance API key from the credentials file into a shell variable, then call the server info endpoint. It is bound to loopback, so run these on the VM (or tunnel port 8082 over SSH).
API_KEY=$(sudo grep '^powerdns.api.key=' /root/powerdns-recursor-credentials.txt | cut -d= -f2-)
curl -s -H "X-API-Key: $API_KEY" http://127.0.0.1:8082/api/v1/servers/localhost | jq '{daemon_type, version}'
sudo rec_control get-all | grep -E '^(questions|cache-hits|cache-misses|cache-entries|all-outqueries)\b'
A request without the key is rejected with HTTP 401, and a request with the key returns HTTP 200:
API_KEY=$(sudo grep '^powerdns.api.key=' /root/powerdns-recursor-credentials.txt | cut -d= -f2-)
echo -n 'with key : HTTP '; curl -s -o /dev/null -w '%{http_code}\n' -H "X-API-Key: $API_KEY" http://127.0.0.1:8082/api/v1/servers/localhost
echo -n 'wrong key : HTTP '; curl -s -o /dev/null -w '%{http_code}\n' -H 'X-API-Key: wrong-key' http://127.0.0.1:8082/api/v1/servers/localhost

Step 7: Review the secure by default configuration
No default or shared credentials ship in the image. The credentials file is 0600 root:root, the API key and webserver password are unique to this VM, and the resolver is not an open resolver: incoming.allow_from is restricted to loopback and RFC1918 private ranges, and the REST API is bound to loopback only.
sudo stat -c '%n perms: %a owner: %U:%G' /root/powerdns-recursor-credentials.txt
sudo grep -vE '^\s*#|^\s*$' /etc/powerdns/recursor.d/cloudimg-recursor.yml
sudo stat -c '%n perms: %a owner: %U:%G' /etc/powerdns/recursor.d/cloudimg-secrets.yml

Step 8: Allow your own clients to resolve
By default only loopback and RFC1918 ranges may query the resolver. To let a specific client subnet resolve, add it as a new list item under incoming.allow_from in the base config and reload. Never add 0.0.0.0/0 — that would make this an open resolver abusable for DNS amplification.
sudoedit /etc/powerdns/recursor.d/cloudimg-recursor.yml
# under the allow_from: list, add a line for your client subnet, for example:
# - <your-mgmt-cidr>
sudo systemctl reload pdns-recursor
Then from a client inside that subnet, point its resolver at this VM's IP and test:
dig @<public-ip> A example.com +short
Step 9: DNSSEC validation
The Recursor validates DNSSEC signed zones. A query for a correctly signed name returns the ad (authenticated data) flag, while a deliberately broken signature fails to resolve — proof the resolver is protecting your clients from tampered answers.
dig @127.0.0.1 A cloudflare.com +dnssec +multiline | grep -E 'flags:|status:'
dig @127.0.0.1 A example.com +dnssec | grep -E 'flags:|status:'
Step 10: Forwarding and RPZ threat filtering
For split horizon or internal domains, forward specific zones to an internal authoritative server by adding a recursor.forward_zones entry (YAML). For DNS firewalling, load a Response Policy Zone (RPZ) so the resolver blocks known malicious domains. These are configured as YAML drop-ins in /etc/powerdns/recursor.d/; see the PowerDNS Recursor documentation for the full schema. Example forward zone drop-in:
recursor:
forward_zones:
- zone: internal.example
forwarders:
- 10.0.0.53
Step 11: Security recommendations
-
Keep the resolver closed to the internet. Only add the specific client subnets that need resolution to
incoming.allow_from. Never add0.0.0.0/0. The NSG should also allow UDP and TCP 53 only from those networks. -
Keep the REST API on loopback. The image binds the API and status webserver to
127.0.0.1and setswebservice.allow_fromto loopback. Do not expose it directly; tunnel port 8082 over SSH if you need it remotely. -
Enable RPZ (Step 10) to block malicious and unwanted domains at the resolver.
-
Restrict administration. Allow TCP 22 for administration only, from your management network.
-
Keep the OS and PowerDNS patched. Unattended security upgrades remain enabled on the running VM, including the official PowerDNS repository for the rec 53 branch.
-
Monitor cache and query rates. Use
rec_control get-allor the REST API metrics to watch query volume, cache hit ratio and servfail rates.
Step 12: Support and Licensing
PowerDNS Recursor is developed by PowerDNS.COM BV and distributed under the GNU General Public License version 2 (GPL-2.0) with an OpenSSL linking exception (see the upstream NOTICE file). This cloudimg image bundles the unmodified official PowerDNS packages. cloudimg provides the packaging, the secure by default configuration, the per instance credential automation, and 24/7 support with a guaranteed 24 hour response SLA.
cloudimg is not affiliated with or endorsed by PowerDNS.COM BV. PowerDNS is a mark of its respective owner and is used here only to identify the software.
Deploy on Azure
Find PowerDNS Recursor on Ubuntu 24.04 LTS on the Azure Marketplace, published by cloudimg. Deploy from the Portal or the Azure CLI as shown above.
Need Help?
Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.