bind_primary¶
The hidden authoritative primary (home, 10.20.30.40) — internal, not in any NS
record. Source of truth for the public zones; serves AXFR (TSIG edge-xfr) to the
edge secondaries and answers RFC2136 ACME updates (TSIG acme) from the origin Caddy.
Config only. This role manages named.conf + the two TSIG key files. The zone
source files and the DNSSEC keys (K*.{key,private,state}) are runtime
state living in /var/named/dynamic — they are not in git (sensitive private
keys + data). On a clean build the zone source files are created here and DNSSEC keys
are generated by the dnssec-policy on first signing; on a rebuild, restore them from
Proxmox/ZFS backup first, then run this role to configure named.
Built-in modules only. Applied by the bind primary play in site.yml (host bind).
Data/state boundary (same as the backends role)¶
| In the role (config) | On the host (state, restored from backup) |
|---|---|
named.conf (zones, dnssec-policy, key-directory) |
dynamic/<zone> source files |
/etc/named/edge-xfr.key, /etc/named/acme.key (from vault) |
dynamic/K*.{key,private,state} DNSSEC keys |
/var/named/dynamic dir (perms/SELinux) |
dynamic/*.signed, *.jnl (named-generated) |
Notes¶
- The TSIG secrets come from vault (
vault_bind_tsig_edge_xfr,vault_bind_tsig_acme, wired ingroup_vars/origin) and match the live key files — re-applying does not rotate them or break AXFR. - BIND on AlmaLinux 9 is 9.16.23-RH;
dnssec-policyhandles key generation and rollover, and the DS published at the registrar must match the active KSK. named-checkconfvalidates before writing; the handler isrndc reconfig(no full restart, so no re-sign churn).
DNS policy enforcement (de-leak Tier-2 names)¶
The zones are runtime state (/var/named/dynamic, restored from backup), so a restore can
reintroduce a public record for a name that should be internal-only (ha + jellyfin once leaked
via CNAME->www). bind_primary_private_names (defaults) lists the Tier-2 names that must be
NXDOMAIN in ${domain}; the dns-reconcile task dig-checks each on the local
authoritative zone and nsupdate-deletes any that have a public record (using the
bind_primary_update_key). It's idempotent (no-op when clean), runs on every converge, and is
runnable alone after a restore: ansible-playbook … -l bind --tags dns-reconcile. To make a name
public, remove it from bind_primary_private_names. (Public names stay in origin_caddy's vhost
list — the two are the codified split-horizon policy.)