After upgrading the Mac client 0.68.3 -> 0.71.3 (matching mgmt) and clearing its NetBird resolver cache (netbird service restart), the managed-zone deletion works: with 0 managed-zone records, the Mac resolves all hubris.network names by forwarding to Technitium (192.168.8.2). iPhone confirmed on cellular (no LAN path -> proves mesh-forward). The first deletion "failure" was a misdiagnosis: the old 0.68.3 resolver cache held stale answers and wouldn't clear on down/up (needs daemon restart); the Mac's dual LAN+mesh paths muddied it. A direct dig @100.122.255.254 of an unsynced name had shown forwarding working. Done: - Deleted all 23 NetBird managed-zone A-records. - Removed the */10 dns-sync cron. Kept /opt/dns-sync/sync.py + token + pre-deletion backup as an emergency-restore tool only. End state: Technitium is the single DNS source. Mesh peers forward to it (Core route -> 192.168.8.0/24); LAN/household query it directly. No replica, no sync. Requires mesh clients on 0.71.x+. Docs: dns.md + 107-dns.md updated to single-source; subdomain recipe no longer references the sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
67 lines
6.3 KiB
Markdown
67 lines
6.3 KiB
Markdown
# 107 — `dns`
|
||
|
||
Homelab DNS server (Technitium). Replaces the dnsmasq that lived on [124 — authentik](124-authentik.md); single-purpose, one job.
|
||
|
||
## At a glance
|
||
- **Hostname:** `dns`
|
||
- **IP:** `192.168.8.2` (static — stable, decoupled from any app)
|
||
- **Privilege:** privileged (Docker-in-LXC, `features: nesting=1`)
|
||
- **Resources:** 1 core / 1 GiB / 8 GiB rootfs
|
||
- **Created:** 2026-06-01, Debian 13. Its own resolver is `1.1.1.1` (no circular dependency on the DNS it serves).
|
||
|
||
## Role
|
||
Authoritative split-horizon DNS for `hubris.network` on the LAN/mesh, plus recursive forwarding (`1.1.1.1`, `8.8.8.8`) for everything else. Technitium runs in Docker (`technitium/dns-server:latest`, `network_mode: host`), web console on `:5380`.
|
||
|
||
## The `hubris.network` zone
|
||
- Specific A overrides: app names → `192.168.8.175` (Caddy), `nfs-export → 192.168.8.200`, `auth/sso/...` as needed.
|
||
- `auth.hubris.network → 82.165.190.79` (VPS Authentik), `sso.hubris.network → 192.168.8.175` (LAN forward-auth outpost).
|
||
- **Wildcard** `*.hubris.network → 82.165.190.79` — mirrors the public IONOS wildcard so undefined names (e.g. `netbird`) resolve to the VPS, matching public behaviour.
|
||
- **MX / SPF-TXT / CAA replicated from public** so an authoritative zone doesn't shadow `hubris.network` email/cert records.
|
||
|
||
## Config / access
|
||
- `/opt/technitium/docker-compose.yml`; admin password in `/opt/technitium/admin_password.txt` (mode 600 — sops-encrypt in Phase 5).
|
||
- Console: `http://192.168.8.2:5380` (user `admin`).
|
||
- API: `http://192.168.8.2:5380/api/...` (token via `/api/user/login`). Zone was built via the API.
|
||
|
||
## Who points here
|
||
- **NetBird mesh peers:** resolve `hubris.network` by **forwarding to Technitium** via the `home-lab-dns` nameserver group (`→ 192.168.8.2`, domain `hubris.network`, applied to all peers). The **NetBird managed DNS zone was removed 2026-06-21 (Phase 4)** — Technitium is now the single DNS source for the mesh too. This works because: (a) roaming peers (`Core`) have the `192.168.8.0/24` route to reach `192.168.8.2` (added 2026-06-21), and (b) clients run NetBird **0.71.x** — on the old 0.68.3 client, forwarding reported `Available` but didn't serve queries, and the resolver cache (`100.122.255.254`) wouldn't clear on `down/up`; a `netbird service restart` (or app toggle) clears it. See [dns.md changelog 2026-06-21](../infrastructure/dns.md).
|
||
- **Homelab DHCP clients:** Technitium's own DHCP scope hands out `192.168.8.2` as the DNS server for `192.168.8.x` leases (see DHCP section below).
|
||
- **Plain LAN clients (`192.168.178.x`):** Fritz!Box DHCP still hands out Fritz!Box itself (`192.168.178.1`) as DNS, **but** the Fritz!Box now *forwards* upstream to Technitium — DNSv4 server set to `192.168.8.2` (Internet → Filter → DNS Server, 2026-06-17). So household clients get split-horizon `*.hubris.network` answers via Fritz!Box→Technitium, with **no NetBird dependency**. (This is the change that decoupled the on-prem tier from the mesh — see [dns.md](../infrastructure/dns.md) 2026-06-17.)
|
||
|
||
## dns-sync (RETIRED 2026-06-21 — Phase 4 complete)
|
||
**The managed-zone sync is no longer scheduled.** `/opt/dns-sync/sync.py` reconciled this zone's named A-records → the NetBird managed DNS zone; the `*/10` cron (`/etc/cron.d/dns-sync`) was **removed 2026-06-21** when the managed zone was retired. Technitium is now the **single** DNS source — mesh peers forward to it (see "Who points here" above), LAN/household clients query it directly.
|
||
|
||
The script + token + a pre-deletion record backup remain at `/opt/dns-sync/` **as an emergency-restore tool only**: running `python3 /opt/dns-sync/sync.py` once re-creates the managed zone from Technitium (used during the Phase 4 rollback). Do not re-add the cron unless reverting Phase 4. Tracked: [scripts/dns-sync.py](../scripts/dns-sync.py).
|
||
|
||
## DHCP
|
||
|
||
Technitium also runs a DHCP server for the homelab subnet (enabled 2026-06-02):
|
||
- **Scope:** `homelab` — `192.168.8.241 – 192.168.8.254`
|
||
- **Gateway:** `192.168.8.1` (Proxmox `vmbr0` alias)
|
||
- **DNS:** `192.168.8.2` (self)
|
||
- **Lease time:** 24 h
|
||
|
||
Replaces the DHCP that was previously served by the Slate AX router. Static-IP LXCs (`.101–.239`) are excluded from the pool. Pool narrowed from `.100–.240` to `.241–.254` on 2026-06-03 to eliminate IP conflict risk.
|
||
|
||
## Related
|
||
- [124 — authentik](124-authentik.md) — retired host of the old dnsmasq
|
||
- [DNS split-horizon](../infrastructure/dns.md)
|
||
- [Mesh](../infrastructure/mesh.md)
|
||
|
||
## Changelog
|
||
|
||
### 2026-06-06 — dns-sync cron installed (had been missing since deployment)
|
||
Although the 2026-06-03 changelog claimed "cron */10", **no crontab was actually configured** on the LXC. The sync was running only via ad-hoc manual invocations during incident debugging. Fixed by adding `/etc/cron.d/dns-sync`.
|
||
|
||
### 2026-06-03 — DHCP pool narrowed to `.241–.254`
|
||
Previous pool `.100–.240` overlapped with all static LXCs/VMs (`.101–.239`). Shrunk via API (`/api/dhcp/scopes/set`). 11 stale DHCP leases in `.101–.110` remain until natural expiry (2026-06-04). See [plan](../plans/2026-06-03-dhcp-pool-exclude-static-ips.md).
|
||
|
||
### 2026-06-03 — dns-sync added (Technitium → NetBird managed zone)
|
||
This Technitium became the single DNS authoring source; `/opt/dns-sync/sync.py` (cron */10) reconciles named A-records into the NetBird managed zone via the API. Fixed previously-broken mesh names (`sso`, `nfs-export`, `mcp`, `secrets`) by adding them to the managed zone; reaped obsolete `files`/`photos-new`. See [dns.md](../infrastructure/dns.md).
|
||
|
||
### 2026-06-02 — DHCP server enabled; replaces Slate AX DHCP
|
||
Enabled Technitium's built-in DHCP server for `192.168.8.0/24` (scope `homelab`, range `.100–.240`, gateway `192.168.8.1`, DNS self). Previously the Slate AX sub-router served DHCP for the homelab subnet. With the Slate AX retired and Proxmox now the subnet router, Technitium takes over DHCP. Configured via the Technitium API (`/api/dhcp/scopes/set`). DHCP LXCs kept their Slate AX leases until expiry, then renewed from Technitium.
|
||
|
||
### 2026-06-01 — created; replaced dnsmasq on 124
|
||
Stood up Technitium at `192.168.8.2`, imported the split-horizon zone (specific A + wildcard + MX/SPF/CAA), made it the primary nameserver in the NetBird `home-lab-dns` group. Verified all names resolve with dnsmasq/124 stopped; [LXC 124 retired](124-authentik.md).
|