Knot DNS Signing Your Zones Itself, Transfers By Key Only

Knot DNS from EPEL as an authoritative server that signs your zones with DNSSEC, keeps your zone files as written and serves a change with no serial to bump. As installed the package cannot start. The live test validates answers with delv against the zone's own key, and is refused a transfer without the TSIG key. Original role, live-tested on Rocky Linux 10.

Verification

Live-tested

Really 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 · attribution

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

README.md, GitLab, Gitea
[![IaC Bazaar: live-tested](https://www.iac-bazaar.com/api/artifacts/ansible-knot/badge)](https://www.iac-bazaar.com/catalog/ansible-knot?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

Ansible role 1.0.0, live-tested on IaC Bazaar: [Knot DNS Signing Your Zones Itself, Transfers By Key Only](https://www.iac-bazaar.com/catalog/ansible-knot?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

```yaml
# Knot DNS Signing Your Zones Itself, Transfers By Key Only: https://www.iac-bazaar.com/catalog/ansible-knot (download from your IaC Bazaar account)
```

Preview:IaC Bazaar: live-tested

Documentation

knot

Knot DNS from EPEL as an authoritative server that signs your zones itself: DNSSEC with ECDSA P-256 and NSEC3 as RFC 9276 recommends, zone files you own and Knot never rewrites, a change served after a reload with no serial to bump, transfers only with a TSIG key the role makes, no recursion, and each file checked by Knot's own parser before it lands. Original role for EL 10, live-tested with podman on Rocky Linux 10.

No download, and no version to pin. EL 10 packages knot 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 role installs knot and knot-utils from EPEL, writes /etc/knot/knot.conf (root:knot 0640: it holds the transfer key) and one zone file per entry in knot_zones under /etc/knot/zones, and enables the package's knot.service, which runs as the knot user. The listener is 127.0.0.1:53 (TCP and UDP) by default; an authoritative server answers on the host's public address, so set knot_listen_address or add knot_extra_listen_addresses. The live test reads the TCP and UDP sockets and expects loopback only.

The package cannot start as installed. dnf prints "warning: group knot does not exist - using root": /etc/knot and knot.conf land root:root, knotd runs as knot, and the unit fails on "no configuration source available" with the package's own file (measured; rpm -V knot shows the group). The role gives /etc/knot back to the knot group.

Signed, and checked from the outside. The live test builds a trust anchor from the zone's own key and validates with delv: a name answers "fully validated", a missing one "negative response, fully validated". NSEC3 uses no salt and no extra iterations (1 0 0 -), as RFC 9276 recommends. To make the zone validate on the internet, publish the DS records keymgr <zone> ds prints at your registrar.

Your zone file stays yours. Knot keeps the signed zone in its journal and never tries to write into the file (zonefile-sync: -1). The file is root:knot 0640, which Knot could not write anyway: with zonefile-sync: 0 it tries after every change and logs "failed to update zone file (operation not permitted)" (measured). A record added to the file with no serial bump is served, signed, after a reload, Knot raising the served serial itself - and Knot's default zonefile-load does that too (measured). What zonefile-load: difference-no-serial adds is a journal that stays consistent: without it, Knot says whole "not compatible with 'journal-content: all'" and warns that with signing and outgoing transfers "'zonefile-load: difference' should be set to avoid malformed IXFR after manual zone file update" (measured). The live test reads Knot's journal for both.

Transfers by key only, and no recursion. A transfer without the key fails, one with a wrong key gets BADSIG, and the key the role makes (/etc/knot/iacbazaar-tsig, root 0600) transfers the zone. A name the server does not hold is REFUSED, and version.bind and id.server answer nothing.

Each file checked first. knot.conf by knotc conf-check; each zone file by Knot's own loader through a throwaway configuration that names the candidate, which refuses a syntax error, a CNAME beside other data and a missing SOA (a missing glue record is only a warning).

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

Live-tested

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.

View module
Live-tested

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.

View module
Live-tested

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.

View module
Live-tested

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.

View module
Live-tested

ansible-pdns-recursor

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.

View module
Live-tested

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.

View module