# PowerDNS Authoritative — upstream documentation Use these when changing `/opt/pdns` on [hk2](../hosts/hk2.chans.xyz.md). Prefer official docs over blog posts. ## Primary references | Topic | URL | |-------|-----| | Settings reference | https://doc.powerdns.com/authoritative/settings.html | | Primary / secondary modes | https://doc.powerdns.com/authoritative/modes-of-operation.html | | Generic PostgreSQL backend | https://doc.powerdns.com/authoritative/backends/generic-postgresql.html | | DNSSEC ops + SOA-EDIT | https://doc.powerdns.com/authoritative/dnssec/operational.html | | DNSSEC advice | https://doc.powerdns.com/authoritative/dnssec/advice.html | | TSIG | https://doc.powerdns.com/authoritative/tsig.html | | HTTP API | https://doc.powerdns.com/authoritative/http-api/ | | Security advisories | https://doc.powerdns.com/authoritative/security-advisories/ | | Docker image (`pdns-auth-50`) | https://hub.docker.com/r/powerdns/pdns-auth-50 | ## Settings we care about on hk2 (ns1) | Concern | Upstream guidance | Our notes (post-2026-08-01) | |---------|-------------------|-----------------------------| | Version | Track advisories; upgrade when Mandatory | Pinned **`powerdns/pdns-auth-50:5.0.6`** (clears 2026-06 + 2026-07) | | Primary | `primary=yes`; zones type MASTER/PRIMARY | Set; zones `windy.me` / `wsvc.info` / `chans.xyz` are Master | | NOTIFY | `also-notify` always notified; empty `only-notify` disables NS-based NOTIFY | `also-notify=202.91.35.141`, `only-notify=` | | AXFR IP ACL | `allow-axfr-ips` limits **unsigned** AXFR | Global + per-zone `ALLOW-AXFR-FROM` → ns2 only | | TSIG AXFR | **Any host with the TSIG key may AXFR**, bypassing IP ACL | Zones use `TSIG-ALLOW-AXFR=mykey.` — rotate/rename key; protect secret | | DNSSEC | `gpgsql-dnssec=yes` + keys via `pdnsutil` | CSK ECDSAP256SHA256 on all three zones | | SOA-EDIT | Needed so non-PDNS secondaries see signature rolls; PDNS secondaries can also compare RRSIGs | `default-soa-edit(-signed)=INCEPTION-INCREMENT` OK (ns2 is PowerDNS). Dig SOA ≠ backend serial is expected | | API key | Prefer `pdnsutil hash-password` (plaintext still accepted) | **Deferred hardening:** live key is weak, plaintext, reused with DB password — rotate | | Webserver | Prefer trusted clients only | Host publishes `127.0.0.1:8081`; `webserver-allow-from` private ranges | | `gpgsql-host` | Prefer IP to avoid resolve chicken/egg | `db` (Compose DNS) is fine inside the stack | | `domains.master` | Used for SECONDARY upstreams | Cleared on MASTER zones (was self-IP noise) | ## Intended `auth/pdns.conf` shape (no secrets) Live file: `/opt/pdns/auth/pdns.conf`. Secrets come from `auth/templates.d/secrets.j2` → `/etc/powerdns/pdns.d/secrets.conf` at container start. ``` local-address=0.0.0.0 local-port=53 launch=gpgsql gpgsql-host=db gpgsql-dnssec=yes include-dir=/etc/powerdns/pdns.d allow-axfr-ips=202.91.35.141 also-notify=202.91.35.141 only-notify= primary=yes secondary=no api=yes webserver=yes webserver-address=0.0.0.0 webserver-port=8081 webserver-allow-from=127.0.0.1,172.16.0.0/12,10.0.0.0/8,192.168.0.0/16 version-string=anonymous disable-syslog=yes loglevel=4 default-soa-edit=INCEPTION-INCREMENT default-soa-edit-signed=INCEPTION-INCREMENT disable-axfr=no ``` Drop-in (from `.env`, never commit): `gpgsql-dbname`, `gpgsql-user`, `gpgsql-password`, `api-key`. ## Deferred hardening (not done yet) 1. Rotate `PDNS_API_KEY` to a long random value; store hashed via `pdnsutil hash-password` if desired; update Poweradmin `.env` / recreate `auth` + `poweradmin`. 2. Rotate `DB_PASS` / Postgres role separately from the API key. 3. Rotate TSIG `mykey` (or rename); confirm ns2 still AXFRs; remember TSIG bypasses `allow-axfr-ips`. ## Related ops docs - Host facts: [hosts/hk2.chans.xyz.md](../hosts/hk2.chans.xyz.md) - Health runbook: [runbooks/pdns-health.md](../runbooks/pdns-health.md) - Routine status: `ansible/playbooks/health-report.yml --limit powerdns` - Reviewed Compose reconciliations: `ansible/playbooks/compose-reconcile.yml` (`auth`, `poweradmin`, and `backup` are the only allowlisted targets)