| 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 |
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.