PowerDNS Recursor Over TLS To Forwarders It Checks By Name
PowerDNS Recursor from EPEL on loopback: DNSSEC validated, and every upstream query sent over DNS-over-TLS with each forwarder's certificate checked against the name it must carry. The live test counts every upstream query as TLS, gets SERVFAIL for a broken signature, and has a copy naming the wrong certificate answer nothing. Original role, live-tested on Rocky Linux 10.
Verification
Live-testedReally deployed to a container sandbox, proven idempotent (a second run changes nothing), verified against the role’s assertions, then torn down.
Conformance
- Static validation (yamllint · ansible-lint)
Provenance
- SHA-256 checksum
- Signature (pending)
Functional
- Live-tested - applied, verified, destroyed
Last verified 2026-10-08 · podman 4.9.3 · ansible 2.21.4 · how we verify
Cite it in your README
badge · attributionPaste this beside the module in the repository that uses it. The badge is rendered from this artifact's verification record, so it reads live-tested because the record says so, and the link lands on this page.
[](https://www.iac-bazaar.com/catalog/ansible-pdns-recursor?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)
Ansible role 1.0.0, live-tested on IaC Bazaar: [PowerDNS Recursor Over TLS To Forwarders It Checks By Name](https://www.iac-bazaar.com/catalog/ansible-pdns-recursor?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)
```yaml
# PowerDNS Recursor Over TLS To Forwarders It Checks By Name: https://www.iac-bazaar.com/catalog/ansible-pdns-recursor (download from your IaC Bazaar account)
```Preview:
Documentation
pdns-recursor
PowerDNS Recursor from EPEL: a caching resolver on loopback that validates DNSSEC and sends every query upstream over DNS-over-TLS, checking each forwarder's certificate against the name it must carry. Original role for EL 10, live-tested with podman on Rocky Linux 10.
No download, and no version to pin. EL 10 packages pdns-recursor in EPEL, so the
role installs it by name and takes what the distribution ships: a security
update arrives through dnf, not through a new release of this role. What the
role owns is the configuration and the proof that the service works.
The distribution's unit, our configuration. The package's unit runs the
recursor as pdns-recursor, Type=notify, already hardened (NoNewPrivileges,
PrivateTmp, PrivateDevices, ProtectClock, two capabilities). The role writes
/etc/pdns-recursor/recursor.yml (root:pdns-recursor 0640) and leaves the
package's recursor.conf alone: with recursor.yml present the recursor reads
it and only it ("YAML config found and processed" - measured). The listener is
127.0.0.1:53 by default; the live test reads the TCP and UDP sockets and
expects loopback only.
Encrypted, and to the right server. dot_to_port_853 makes the recursor
speak TLS to a forwarder on port 853 - the live test counts every upstream query
as DNS-over-TLS and none over plain TCP - but the schema's default is an empty
tls_configurations, which asks for no certificate check. The role adds one per
certificate name in pdns_recursor_forwarders, with validate_certificate: true and the name the forwarder must present (Quad9's is dns.quad9.net). The
live test proves the check is enforced rather than configured: a copy of the
deployed file run on another port resolves as deployed, and the same copy
naming wrong.example answers SERVFAIL and logs "hostname mismatch" (the
test's copies turn on verbose_logging so that the reason is on record).
Validated. dnssec.validation: validate: a signed name comes back with the
ad flag, and a domain whose signatures are deliberately broken
(dnssec-failed.org) gets SERVFAIL - and resolves with checking disabled (+cd),
so the SERVFAIL is the validation and not the network. The broken name is asked
without the AD bit, because dig sets it by default and with it even the
package's process mode validates (measured: a test run set to process
passed the plain query); asked bare, only validate refuses it.
Checked before it lands. pdns_recursor --config=check reads the
configuration from a directory, so the role's
/usr/local/libexec/iacbazaar-pdns-recursor-check checks the candidate as the
only file in a directory of its own: an unknown field is refused by name, with
the valid ones listed (measured).
Forwarding is the default, recursion is the switch. Set
pdns_recursor_forwarders: [] to resolve from the root servers instead.
License
Commercial - IaC Bazaar EULA. (c) IaC Bazaar.
Usage code & full reference need an account
The complete copy-paste usage, the full input/output reference, and operational notes are free with an account - shown here and bundled in the download. Sign in and this section fills in.
- Variables
- Test
Related modules
ansible-unbound-resolver
Unbound on loopback: DNSSEC validated locally against the root anchor, query names minimised, version hidden, and upstream over DNS-over-TLS by default because many networks reset TCP 53 to anything but a known resolver, which breaks full recursion the moment a DNSKEY answer outgrows UDP. Recursion is one setting away. Original role, live-tested on Rocky Linux 10.
ansible-bind-authoritative
BIND as an authoritative-only server. The package is a loopback resolver; add a zone and anyone who can query can copy the whole zone, and version.bind names the 9.18 to attack. This role turns recursion off, refuses transfers to anyone not listed, hides the identity records, rate-limits responses, and renders zones from data checked before they land. Original role, live-tested on Rocky Linux 10.
ansible-coredns
CoreDNS from the upstream release (sha256-verified) as a hardened system service answering authoritatively for your zones on 127.0.0.1:53 as a system user (CAP_NET_BIND_SERVICE through the unit), forwarding only when you name upstreams. The live test digs the example zone's A record with the aa flag, an NXDOMAIN in the zone and a REFUSED outside it. Original role, live-tested on Rocky Linux 10.
ansible-nsd
NSD from EPEL: an authoritative-only server for your zones, the configuration and every zone checked by NSD's own tools first, transfers only to the addresses and TSIG keys you name, response rate limiting, and the state directory the package leaves unwritable fixed. The live test gets the zone with the key and is refused without it. Original role, live-tested on Rocky Linux 10.
ansible-powerdns
PowerDNS authoritative from EPEL with its SQLite backend; the live test adds a zone through the API, gets the record from dig and NXDOMAIN for an unknown name, sees the API refuse a caller with no key, and reads the query counter. The schema is recovered when a docs-stripped host lacks it. Original role, live-tested on Rocky Linux 10.
ansible-bind-exporter
bind_exporter on EL 10 from the upstream release (sha256-verified), as a hardened systemd service on loopback; the live test brings up named with one zone and a statistics channel on loopback as a fixture, asks it a name with dig, and reads bind_up 1 and the A query counted. Original role, live-tested on Rocky Linux 10.