wiki-vault/Sources/Homelab/homelab-dns-decision.md
Travis Herbranson 34a268d8dc migration: copy 62 notes from pbs-projects and homelab-projects
Two-layer structure: Sources (raw notes) + Wiki (compile output)
Four domains: Dev (40), Venture (3), Homelab (23), Reference (0)
Includes CLAUDE.md spec, index pages at all levels, compile log

Co-Authored-By: Lovebug <lovebug@herbylab.dev>
2026-05-08 17:21:13 -04:00

4.2 KiB

created path project status tags type updated
2026-05-06 Sources/Homelab homelab-dns-decision active
homelab
dns
knot
pihole
unbound
traefik
session-notes 2026-05-06

Homelab DNS — Architecture Decision

Outcome

Locked the internal DNS architecture. Knot DNS as a dedicated authoritative server for herbylab.dev, running active/passive across Proxmox and the NAS. Pi-hole + Unbound stays as the recursive frontend and ad-blocker.

Architecture

Client → Pi-hole (ad-block + cache) ├─ herbylab.dev queries → Knot (authoritative) └─ everything else → Unbound → root servers

Split-horizon: *.herbylab.dev resolves internally to the Traefik VM IP via Knot. Cloudflare remains public authoritative for the same zone. Same name, different answer depending on who's asking.

Decisions

Decision Choice Rationale
Authoritative DNS Knot DNS Purpose-built authoritative, native
AXFR/NOTIFY, ~40MB RAM, zone files in plain text, knotc CLI for runtime
changes
Recursive + ad-block Pi-hole + Unbound (kept) Already works, no
reason to replace the recursive layer just because zone management is
clunky
Redundancy model Active/passive, separate hosts Knot primary on PVE,
secondary on NAS — separate failure domains
Replication Native AXFR + NOTIFY Edit primary, secondary auto-syncs.
No Ansible run per record change
Source of truth Zone file in git Versioned, debuggable, deployed to
primary via Ansible
Failover at client OpenWrt DHCP hands out both Pi-hole IPs
Active/passive at the resolver level. Adds the second Pi-hole to the
existing pattern
DHCP Stays on OpenWrt Knot doesn't touch DHCP
Internal certs Wildcard *.herbylab.dev via Traefik + Cloudflare
DNS-01 Real LE cert, no browser warnings, independent of internal DNS
layer. Works because Cloudflare owns the public zone — LE never touches the
internal IP
Zone structure Flat (one zone for all *.herbylab.dev) Single source
of truth; revisit if it gets unwieldy

Why Not the Other Contenders

  • Technitium — right answer when replacing Pi-hole + Unbound entirely. Overkill once Pi-hole stays.
  • PowerDNS — sexy on paper (REST API, web UI option) but adds SQL backend, second daemon for the UI, heavier replication setup. Can write a custom GUI on top of Knot later if needed.
  • CoreDNS — fine, but not really designed for primary/secondary AXFR. Better fit for K8s-style deployments.
  • NSD — close runner-up. Knot edged it on the knotc runtime CLI and slightly nicer config syntax.
  • BIND9 — overkill, config-heavy. Skipped.

Key Learnings

  • Internal certs are a naming problem, not a DNS problem. Using herbylab.dev for internal names (split-horizon) means a public CA will sign a wildcard cert via DNS-01. A .lan or .internal zone forces a private CA + root cert distribution — not worth it.
  • The job defines the tool. Original DNS contender list (Technitium, CoreDNS, PowerDNS, BIND9) assumed a full Pi-hole + Unbound replacement. Once Pi-hole stays, the job collapses to "small authoritative server, one zone, easy to replicate" — different list (Knot, NSD, CoreDNS, PowerDNS).
  • Cloudflare, Tailscale, Traefik, internal DNS each do one thing. Cloudflare = public auth + ACME validation. Tailscale MagicDNS = device naming on the tailnet. Traefik = service routing once a request lands. Internal DNS = telling LAN clients where to send the packet. They don't overlap, they compose.

Open Items

  • Stand up second Pi-hole instance for redundancy (parallel to Knot work, not blocking)
  • Decide Pi-hole sync method (gravity-sync vs Teleporter)
  • Pick deployment unit for Knot on each host (LXC on PVE likely; Docker on NAS)
  • Initial zone file content — inventory current *.herbylab.dev records to migrate from Pi-hole local DNS
  • TTL strategy — start at 300 during buildout, raise to 3600 once stable
  • Ansible role for Knot primary deployment
  • Confirm Pi-hole conditional forwarding config for herbylab.dev → Knot

Next Session

Return to the Traefik chat with this decision locked. DNS slot in the broader stack is now filled.

...sent from Jenny & Travis