Connect your own nameserver (PowerDNS)
A self-hosted provider is a nameserver you run yourself, on premises or on a VPS, next to the cloud providers of a zone. RedundantDNS writes the zone to it through the PowerDNS Authoritative HTTP API, exactly as it writes to Route 53 or Cloudflare: same canonical zone, same diff, same drift checks, and your nameserver's names join the zone's NS set.
The quickest way to get a suitable server is the open-source
selfhost-ns bundle
(Docker Compose or systemd, hardened defaults). Any PowerDNS Authoritative
4.x with the API enabled works too.
The API key is encrypted with your organization's key as soon as it reaches us, is never shown again, and is only used to read and write the zones you attach.
| Access level | What RedundantDNS can do |
|---|---|
| Create and manage zones | Create zones on your server, write their records, and delete a zone when you detach it (only after you type the zone name). |
| Manage an existing zone | Read and edit the records of one zone you created on your server. It never creates or deletes zones. |
| Mirror source (read-only) | Only read one zone you keep editing on your server. RedundantDNS mirrors it to your other providers and never writes to it. |
PowerDNS API keys are server-wide: every level uses the same key, and the
level only limits what RedundantDNS does with it. Create a dedicated server
(or at least a dedicated key, see below) for RedundantDNS. The API is
enabled in pdns.conf:
api=yes
api-key=<api key>
webserver=yes
webserver-address=127.0.0.1
webserver-port=8081
webserver-allow-from=127.0.0.1
Put the TLS reverse proxy (see below) in front of 127.0.0.1:8081.
Read this first: what your server must offer
- The API, reachable by RedundantDNS over https. The PowerDNS
webserver speaks plain http; put a TLS reverse proxy in front of it
(Caddy, nginx) and allow only RedundantDNS's addresses, or reach it over
a VPN. RedundantDNS refuses
http://API URLs and API URLs that resolve to private, loopback or link-local addresses; a self-installed platform on the same private network as its nameservers can list them inRDNS_SELFHOST_PRIVATE_ALLOWLIST(CIDRs, IPs orIP:portpairs; plain http only for a URL whose host is a literal IP in the list). - DNS on port 53, UDP and TCP, to the whole internet, on the addresses your nameserver names resolve to.
- Nameserver names (
ns1.example.net) with A/AAAA records pointing to the server. These are the names you enter in the connection; they are added to the NS set of every zone attached to it. If the names live inside the zone they serve, your registrar also needs glue records. - No recursion and a hidden version: an authoritative-only server
(the
selfhost-nsbundle does this for you).
Record types: A, AAAA, CNAME, MX, TXT, SRV, CAA, NS and PTR, with any TTL from 1 second, wildcards, and no limit on values per record set. PowerDNS also serves TLSA, HTTPS, SVCB and more; RedundantDNS will write them once its canonical model carries them. A CNAME at the zone apex is refused (it cannot coexist with the SOA and NS records).
1. Collect the connection values
| Field | Where it comes from |
|---|---|
| PowerDNS API URL | The https URL of the API, e.g. https://pdns-api.example.net. A trailing /api/v1 is accepted. |
| API key | The api-key of pdns.conf (scripts/init.sh of selfhost-ns generates one and prints it). |
| Nameservers | The NS names this server answers as, comma separated: ns1.example.net, ns2.example.net. One at least. |
| Server ID (optional) | PowerDNS's server id, localhost unless you renamed it. |
2a. Create and manage zones
In RedundantDNS, Providers → Add connection: provider Self-hosted
(PowerDNS), access level Create and manage zones, fill the fields above,
then click Test and save. We check the key by reading the server
(GET /api/v1/servers/localhost) and that it is an authoritative server.
When you attach the connection to a zone, RedundantDNS creates it on your
server as a Native zone (no AXFR between PowerDNS servers) with
soa_edit_api: DEFAULT, so PowerDNS increases the SOA serial on every
change.
2b. Manage an existing zone
Create the zone on your server yourself, for example:
pdnsutil create-zone example.com ns1.example.net
pdnsutil set-meta example.com SOA-EDIT-API DEFAULT
pdns_control rediscover
SOA-EDIT-API DEFAULT makes PowerDNS increase the SOA serial on every
change RedundantDNS makes (a zone created with pdnsutil has no such
setting, and its serial would stay where it is). pdns_control rediscover
makes the running server load the new zone at once: until then, or until
its zone cache refreshes (zone-cache-refresh-interval, 300 seconds by
default), it answers REFUSED for the zone, and the zone's health shows
degraded even though the records are in sync.
Add the connection with access level Manage an existing zone. The key is
checked when you attach the connection to a zone: open the zone,
Providers → Attach, pick the connection and give the zone name
(example.com.; the trailing dot is optional) as the zone ID. We verify
that the zone exists and holds the same domain.
2c. Mirror source (read-only)
Use this when the zone stays edited on your server (with pdnsutil, your
own tooling or a hidden primary) and RedundantDNS only copies it to your
other providers. RedundantDNS reads the zone with GET requests and
never writes to it. Add the connection with access level Mirror source
(read-only), or use Zones → New zone → Mirror an existing zone and
give the zone name (example.com.) as the zone ID. The NS plan starts
as the zone's own apex NS set.
What RedundantDNS writes
- Every record set you manage in the dashboard. A change goes to PowerDNS
as one
PATCH /api/v1/servers/<id>/zones/<zone>request:REPLACEfor created and updated record sets andDELETEfor removed ones, applied by PowerDNS in a single transaction. Both are idempotent, so a retry after a network error converges. - The apex NS set: the nameservers of every active provider of the zone, including the names of this connection. A standby attachment receives the records only: its apex NS set is left as it is.
- Nothing in the SOA (PowerDNS maintains the serial).
A record you change directly on the server (with pdnsutil or the API) is
reported as drift, never overwritten silently. Disabled records are
ignored, and record types RedundantDNS does not model yet (DNSSEC records,
TLSA, ...) are left alone.
Limits in this version
- Query metrics are not read (PowerDNS statistics are server-wide, not per zone).
- AXFR mode (RedundantDNS as a hidden primary with TSIG, for servers
whose API cannot be exposed) and several nameserver identities per host
come next; see the
selfhost-nsroadmap. - DNSSEC is not managed: if you sign zones on your server, the other providers of the zone do not serve the same signatures.
Troubleshooting
| Message | Meaning |
|---|---|
HTTP 401: the API key was rejected | The key does not match api-key in pdns.conf. |
HTTP 404 on the connection test | The server ID is not localhost (check GET /api/v1/servers), or the URL points to something that is not the PowerDNS API. |
apiUrl must use https | Put a TLS proxy in front of the API (see above). |
the API address is not public | The API URL resolves to a private or loopback address. |
HTTP 422: ... Conflicts with pre-existing RRset | A CNAME and another record share a name on the server (often a record created by hand). |
HTTP 409: Domain 'example.com.' already exists | The zone already exists on the server: adopt it when the dashboard offers to. |