Skip to content

PowerDNS

David Humphrey edited this page Nov 30, 2022 · 11 revisions

Overview

Starchart uses the PowerDNS Authoritative Server for our DNS management. We chose it due to its ability to dynamically manage DNS records via an API.

This page collects various pieces of information related to PowerDNS, how we use it, and links to resources we need.

Resources

Running the Authoritative Server via Docker

Docker Hub Images

The "auth" server (short for Authoritative) can be run from Docker using one of the various the official powerdns/pdns-auth-* images on Docker Hub. NOTE: unlike many other Docker images, PowerDNS uses image names vs. tags to do releases. For example:

Running a Container

To run a container based on v4.7.x (there is likely a newer release) locally, you can do the following:

docker run \
  --rm \
  --name pdns-auth \
  --env PDNS_AUTH_API_KEY=secret_key \
  -p 1053:53 -p 1053:53/udp -p 8081:8081 \
  powerdns/pdns-auth-47

This command does the following:

  1. Starts a new container based the powerdns/pdns-auth-47 image, which will be removed automatically when we are finished
  2. Names the container pdns-auth
  3. Defines the PDNS_AUTH_API_KEY to be secret_key, which is needed to access the web API
  4. Publishes 3 separate ports on the host (1053 tcp, 1053 udp, and 8081)

You can also add a trailing -d to run it in the background:

docker run \
  --rm \
  --name pdns-auth \
  --env PDNS_AUTH_API_KEY=secret_key \
  -p 1053:53 -p 1053:53/udp -p 8081:8081 \
  powerdns/pdns-auth-47 \
  -d

You can now login to the web server at http://127.0.0.1:8081 using the following credentials:

  • username: root
  • password: secret_key

Similarly, you can access the HTTP API by including the PDNS_AUTH_API_KEY we specified above:

$ curl -s -H "X-API-Key: secret_key" http://127.0.0.1:8081/api/v1/servers/localhost
{"autoprimaries_url": "/api/v1/servers/localhost/autoprimaries{/autoprimary}", "config_url": "/api/v1/servers/localhost/config{/config_setting}", "daemon_type": "authoritative", "id": "localhost", "type": "Server", "url": "/api/v1/servers/localhost", "version": "4.7.2", "zones_url": "/api/v1/servers/localhost/zones{/zone}"}

Interacting with the Server using pdnsutil

We can now experiment with the server using the pdnsutil cli. An easy way to get access to a shell with everything you'll need is to use the following command:

docker exec -it pdns-auth /bin/bash

Now you can use pdnsutil against the running server. Here are some examples you can try:

# Create a zone
$ pdnsutil create-zone example.com
Creating empty zone 'example.com'

# Add a root A Record 
$ pdnsutil add-record example.com @ A 192.168.1.2
New rrset:
example.com. 3600 IN A 192.168.1.2

# Add a host (not: this is not a subdomain!)
$ pdnsutil add-record example.com www A 192.168.1.2
New rrset:
www.example.com. 3600 IN A 192.168.1.2

# Add a TXT record hello with value "world"
$ pdnsutil add-record example.com hello TXT 3600 "world"
New rrset:
hello.foo.com. 3600 IN TXT "world"

# Delete a TXT record named `hello`
$ pdnsutil delete-rrset example.com hello TXT

# List records for example.com
$ pdnsutil list-zone example.com
$ORIGIN .
example.com	3600	IN	A	192.168.1.2
example.com	3600	IN	SOA	a.misconfigured.dns.server.invalid hostmaster.example.com 0 10800 3600 604800 3600
www.example.com	3600	IN	A	192.168.1.2

When you're done, you can exit the shell, and stop the running container with CTRL+C

Interacting with the Server using the HTTP API

We can accomplish the same sorts of things using the HTTP API.

NOTE: the server is accessible at port 8081 of our host (e.g., http://127.0.0.1:8081). Also, every API call will require us to include the X-API-Key header, using the value we specified above in our PDNS_AUTH_API_KEY environment variable.

# Create a zone (not sure what kind should be, see:
# https://doc.powerdns.com/authoritative/http-api/zone.html#objects)
curl -s \
  -H "X-API-KEY: secret_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "bar.com.", "kind": "Native"}' \
  http://127.0.0.1:8081/api/v1/servers/localhost/zones
{"account": "", "api_rectify": false, "catalog": "", "dnssec": false, "edited_serial": 2022112401, "id": "bar.com.", "kind": "Native", "last_check": 0, "master_tsig_key_ids": [], "masters": [], "name": "bar.com.", "notified_serial": 0, "nsec3narrow": false, "nsec3param": "", "rrsets": [{"comments": [], "name": "bar.com.", "records": [{"content": "a.misconfigured.dns.server.invalid. hostmaster.bar.com. 2022112401 10800 3600 604800 3600", "disabled": false}], "ttl": 3600, "type": "SOA"}], "serial": 2022112401, "slave_tsig_key_ids": [], "soa_edit": "", "soa_edit_api": "DEFAULT", "url": "/api/v1/servers/localhost/zones/bar.com."}

# todo, finish similar examples with API...
# See tests for hints at https://github.com/PowerDNS/pdns/blob/master/regression-tests.api/test_Zones.py