Deployment guide

gdnsd

Overview

gdnsd is a fast, lightweight, authoritative-only DNS server. It is a single compiled daemon that publishes the DNS records for the domains you own and answers queries for those zones directly from memory. It is well known for weighted, health-checked and geographic load balancing answers. It is not a recursive resolver, so it never resolves names on behalf of clients.

This guide covers the deployment and configuration of gdnsd on Ubuntu 24.04 on Azure using SecureAnyCloud Azure Marketplace images. The image builds gdnsd 3.8.3 from the official upstream source release (checksum verified). It runs under systemd as an unprivileged gdnsd user with just the CAP_NET_BIND_SERVICE capability, so it can bind the standard privileged DNS port without running as root.

gdnsd answers DNS on port 53 over both UDP and TCP across all interfaces. There is no web interface and no database. The configuration file (/etc/gdnsd/config) plus plain text zone files in /etc/gdnsd/zones are the whole configuration. You administer the server locally with the gdnsdctl tool over a private unix control socket that is not reachable over the network.

Secure by default: authoritative only. A naively deployed public resolver can be abused for DNS amplification attacks. gdnsd avoids this entirely because it is authoritative only. It answers only for the zones you configure and never recurses, so any query for a name outside your zones is answered REFUSED.

gdnsd also does not serve zone transfers, so an AXFR request from an unauthorized client cannot dump your zone. On the first boot of every VM, the instance IP is baked into a demonstration zone, so DNS answers immediately. gdnsd has no login, so no shared or default credential of any kind ships in the image.

What you get:

  • gdnsd 3.8.3 built from the official upstream source release, run under systemd as the unprivileged gdnsd user (gdnsd.service).
  • A DNS endpoint on 0.0.0.0:53 and [::]:53 over both UDP and TCP.
  • An authoritative demonstration zone, example.sac.invalid, served with the authoritative answer (AA) flag. Its records point at this instance's IP, which is baked in on first boot.
  • A working weighted and multi-address failover resource served through gdnsd's multifo plugin as the dynamic record lb.example.sac.invalid, which needs no external database.
  • The geoip plugin compiled in and ready for geographic load balancing once you supply your own MaxMind database.
  • The whole configuration in readable text, /etc/gdnsd/config plus zone files, that you can version control and reload with a single command.
  • Local-only administration over the gdnsdctl control socket. The systemd-resolved stub listener is disabled, so gdnsd owns port 53 cleanly while the OS keeps resolving names through the upstream resolver list.

Prerequisites

  • An Azure subscription with permission to deploy virtual machines.
  • A resource group and virtual network, or let the portal create them during deployment.
  • A network security group that allows inbound UDP and TCP port 53 from the clients that will query your name server, and TCP port 22 from your management address for SSH.
  • To serve a real domain, the ability to set the domain's NS delegation at your registrar to point at this instance.
1

Deploy from the Azure Portal

Open the SecureAnyCloud gdnsd on Ubuntu 24.04 LTS offer in the Azure Marketplace. Select Get It Now, then Create.

Choose your subscription, resource group, region and VM size. A Standard_B2s is a comfortable starting point for an authoritative name server.

Under Networking, attach or create a network security group that allows inbound UDP 53 and TCP 53 from your clients and TCP 22 from your management address.

Review and create. When the deployment finishes, note the VM's public IP address.

2

Deploy from the Azure CLI

az group create --name gdnsd-rg --location eastus
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:gdnsd-ubuntu-24-04:default:latest
az vm create \
  --resource-group gdnsd-rg \
  --name gdnsd-vm \
  --image sac1647283583153:gdnsd-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group gdnsd-rg --name gdnsd-vm --port 53 --priority 1001

Replace <sac-gdnsd-image-urn> with the image reference from your Marketplace subscription.

The az vm open-port command opens port 53 in the VM's network security group. Open it for both UDP and TCP to the client ranges that will query your server.

3

First boot

On the first boot of each VM, a one-shot service, gdnsd-firstboot.service, resolves the instance's IP address and renders the demonstration zone example.sac.invalid with that IP. It writes an informational note to /root/gdnsd-info.txt, and then systemd starts gdnsd.

gdnsd has no login, so this note holds no secret. First boot completes within a few seconds of the VM becoming reachable.

4

Confirm the service is running

SSH to the VM and confirm that gdnsd is active and owns port 53 over both UDP and TCP:

systemctl is-active gdnsd.service gdnsd --version ss -tuln | grep ':53 '

The output shows the service as active, gdnsd reporting version 3.8.3, and listeners bound on port 53 for both UDP and TCP on IPv4 and IPv6.

5

Query the authoritative demo zone

Query the demonstration zone on the loopback interface. gdnsd answers authoritatively, so the response header carries the aa (authoritative answer) flag:

dig @127.0.0.1 example.sac.invalid SOA +short dig @127.0.0.1 example.sac.invalid NS +short dig @127.0.0.1 demo.example.sac.invalid A

The SOA and NS queries return the zone's start of authority and name server records. The demo record returns an A record pointing at this instance's IP.

Look for flags: ... aa in the header of the demo answer. It confirms that the answer is authoritative.

6

Weighted failover and runtime statistics

The image ships a working weighted, all active failover resource served through gdnsd's multifo plugin as the dynamic record lb.example.sac.invalid. It returns a mapped set of addresses and needs no external database. Runtime statistics are read locally with gdnsdctl over the control socket:

dig @127.0.0.1 lb.example.sac.invalid A +short
sudo gdnsdctl stats

The lb query returns the mapped address set from the multifo resource. gdnsdctl stats prints JSON runtime statistics gathered over the private control socket. The control socket is a local unix socket at /run/gdnsd/control.sock, and it is not reachable over the network.

7

Confirm the server is authoritative only

gdnsd never recurses. Query the instance on its routable address to confirm two things. A query for a name outside your zones is answered REFUSED, and a zone transfer request from an unauthorized client is refused:

IP=$(hostname -I | awk '{print $1}') dig @"$IP" www.example.com A | grep -E 'status:' dig @"$IP" example.sac.invalid AXFR | tail -3

The out-of-zone query returns status: REFUSED. This proves the server is not an open resolver and cannot be used as a DNS amplification vector.

The AXFR request reports Transfer failed. This proves zone transfers are not served to unauthorized clients.

8

Serve your own authoritative zone

gdnsd derives each zone's name from its file name in /etc/gdnsd/zones. To serve a new zone, drop in a zone file named after the zone. Create a zone file for your domain and reload:

sudo tee /etc/gdnsd/zones/<your-domain> >/dev/null <<'ZONE' $TTL 3600 @ SOA ns1 hostmaster ( 1 ; serial 7200 ; refresh 3600 ; retry 1209600 ; expire 3600 ; ncache ) @ NS ns1 ns1 A 203.0.113.10 @ A 203.0.113.10 www A 203.0.113.10 ZONE
sudo gdnsdctl reload-zones

Replace <your-domain> with your domain name (for example example.com) and the addresses with your own. gdnsdctl reload-zones reloads the zones with no downtime.

Then delegate the domain at your registrar by setting its NS records to point at this instance.

9

Weighted and geographic load balancing

gdnsd is well known for returning different answers based on weight, health and client geography. The shipped multifo resource in /etc/gdnsd/config gives you all-active failover out of the box:

sudo cat /etc/gdnsd/config

To weight backends unevenly, use the weighted plugin. To fail over based on health checks, attach a service_types monitor to the resource. For geographic answers, enable the compiled-in geoip plugin.

MaxMind licenses its GeoIP databases directly to each end user, so this image does not ship a MaxMind database. Download your own MaxMind database and accept MaxMind's terms with MaxMind. Place the .mmdb file on the VM, and reference it from a geoip resource in the configuration.

SecureAnyCloud support can help you design weighted, health-checked and geographic resources for your traffic.

10

Review the configuration and info note

sudo cat /etc/gdnsd/config
sudo cat /root/gdnsd-info.txt ls -l /etc/gdnsd/zones

The configuration file is the single source of truth for options and plugin resources. The zones directory holds one file per zone, and the info note summarizes this instance. The note holds no secret, because gdnsd has no login.

11

Security recommendations

  • Open port 53 only to the clients that need it. Authoritative servers for a public domain must accept queries from the internet, but you can still restrict management access. Keep TCP 22 limited to your management address.
  • Keep it authoritative only. This image never recurses, which is what makes it safe to expose publicly. Do not add forwarding or recursion. If you need a resolver for your own clients, run a separate recursive resolver.
  • Administer locally. The gdnsdctl control socket is a local unix socket and is not exposed on the network. Manage the server over SSH.
  • Run more than one name server. For production, delegate your domain to at least two authoritative servers in different locations, each running this image, so your DNS survives the loss of any single instance.
  • Keep the OS patched. The image is patched at build time and ships with unattended security updates enabled, so it keeps receiving fixes.
12

Support and Licensing

gdnsd is free software published under the GNU General Public License version 3 (GPL-3.0). This image builds gdnsd from the official upstream source release.

gdnsd is a trademark of its respective owner, and MaxMind, GeoIP and GeoLite are trademarks of MaxMind, Inc. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by the gdnsd project or MaxMind, Inc. All product names are used for identification only.

SecureAnyCloud provides 24/7 technical support for this product by email (sales@secureanycloud.com) and live chat. Support covers deployment and first boot configuration, zone design, weighted and multi-address failover, geographic load balancing with your own MaxMind database, high-availability name server design, registrar delegation, version upgrades, performance tuning and troubleshooting. Critical issues receive a one-hour average response time.

Deploy on Azure

Launch gdnsd 3.8.3 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure