research: private DNS for dev/homelab names (tailnet now, homelab later) #213

Open
opened 2026-10-15 23:32:19 -04:00 by jfraeys · 2 comments
Owner

Research issue: no implementation yet. Goal is to decide how to name hosts and services on private networks (the tailnet now, a homelab later) without typing IPs.

Questions to answer

  1. Suffix: a subdomain of a domain I own (e.g. lab.jfraeys.com / home.jfraeys.com, real Let's Encrypt certs via the DNS challenge) vs .internal (reserved for private use, needs a private CA). .local is out: it is mDNS, and Let's Encrypt will not issue for it.
  2. Resolver: Headscale extra_records + MagicDNS (nothing new to run) vs dnsmasq / CoreDNS (files) vs AdGuard Home / Technitium / Pi-hole (UI, wildcards, ad-blocking).
  3. Split DNS: can Tailscale/Headscale send only the private suffix to a chosen resolver, and does that work on every client I use (macOS, Linux, phone)?
  4. Certificates: which DNS provider hosts the zone for the ACME DNS challenge (Cloudflare today, deSEC is built but not live), and does a private subdomain add anything public beyond hostnames?
  5. Resilience: where does the resolver run so that losing one host does not lose name resolution (second resolver, public fallback)?
  6. Fit with this repo: a generic dns_resolver role (records from a vars file) or only Headscale config? What does the tailnet-only service list need today?

Constraints

  • The services node is memory-starved until the OVH move (#187); anything added must be small.
  • Roles stay generic and reusable (homelab later).
  • Do not expose the resolver to the internet; reach it over the tailnet.

Options considered so far

Option Cost Fit
Headscale extra_records none a few named tailnet hosts
dnsmasq / CoreDNS ~1 MB wildcards, file-driven
Technitium / AdGuard Home ~100-200 MB UI, per-client rules
Pi-hole similar if ad-blocking is the goal
Unbound / BIND heavy config overkill

Definition of done for this issue

A short recommendation written into this issue: suffix, resolver, split-DNS approach, and whether it needs a role. Implementation gets its own issue.

Research issue: no implementation yet. Goal is to decide how to name hosts and services on private networks (the tailnet now, a homelab later) without typing IPs. ## Questions to answer 1. **Suffix:** a subdomain of a domain I own (e.g. `lab.jfraeys.com` / `home.jfraeys.com`, real Let's Encrypt certs via the DNS challenge) vs `.internal` (reserved for private use, needs a private CA). `.local` is out: it is mDNS, and Let's Encrypt will not issue for it. 2. **Resolver:** Headscale `extra_records` + MagicDNS (nothing new to run) vs dnsmasq / CoreDNS (files) vs AdGuard Home / Technitium / Pi-hole (UI, wildcards, ad-blocking). 3. **Split DNS:** can Tailscale/Headscale send only the private suffix to a chosen resolver, and does that work on every client I use (macOS, Linux, phone)? 4. **Certificates:** which DNS provider hosts the zone for the ACME DNS challenge (Cloudflare today, deSEC is built but not live), and does a private subdomain add anything public beyond hostnames? 5. **Resilience:** where does the resolver run so that losing one host does not lose name resolution (second resolver, public fallback)? 6. **Fit with this repo:** a generic `dns_resolver` role (records from a vars file) or only Headscale config? What does the tailnet-only service list need today? ## Constraints - The `services` node is memory-starved until the OVH move (#187); anything added must be small. - Roles stay generic and reusable (homelab later). - Do not expose the resolver to the internet; reach it over the tailnet. ## Options considered so far | Option | Cost | Fit | |---|---|---| | Headscale `extra_records` | none | a few named tailnet hosts | | dnsmasq / CoreDNS | ~1 MB | wildcards, file-driven | | Technitium / AdGuard Home | ~100-200 MB | UI, per-client rules | | Pi-hole | similar | if ad-blocking is the goal | | Unbound / BIND | heavy config | overkill | ## Definition of done for this issue A short recommendation written into this issue: suffix, resolver, split-DNS approach, and whether it needs a role. Implementation gets its own issue.
Author
Owner

Split into two issues: #241 (implementation: dns.extra_records from a role variable; MagicDNS with base_domain ts.jfraeys.com is already enabled) and #242 (decisions: names, certificates, cutover behavior, servers and DNS, homelab). Recommendation unchanged: Headscale extra_records now, a real resolver with split DNS later for the homelab.

Split into two issues: #241 (implementation: dns.extra_records from a role variable; MagicDNS with base_domain ts.jfraeys.com is already enabled) and #242 (decisions: names, certificates, cutover behavior, servers and DNS, homelab). Recommendation unchanged: Headscale extra_records now, a real resolver with split DNS later for the homelab.
Author
Owner

Operator decision: keep Traefik as the reverse proxy (also for the homelab). The earlier mention of Caddy as an option is withdrawn.

Operator decision: keep Traefik as the reverse proxy (also for the homelab). The earlier mention of Caddy as an option is withdrawn.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jfraeys/infra#213
No description provided.