Added an internet-independent local access path for all homelab services: a *.telep.lan wildcard DNS record on telep-router pointing every name at the mainframe, plus a Caddy v2 reverse proxy on telep-mainframe that maps stable *.telep.lan names to each backend. Home or away, internet or not, every service is reachable by a stable name; Tailscale remains for remote access.
Caddy is a single point of failure for ALL domain access — and it lost a boot-race for ~1.6 days
On 2026-08-17 this Caddy was found
failedsince the 2026-08-15 YubiKey reboots: it started before the LAN IP192.168.1.123was assigned and could not bind:443, taking down every*.telep.lanname AND bothlevandor.ioportals by-domain — silently. Fixed withnet.ipv4.ip_nonlocal_bind=1+ a restart drop-in. Full write-up below (Caddy boot-race outage (2026-08-17)); runbook caddy-boot-race.
Motivation
Tailscale-only exposure means services vanish when there is no internet (and some services were bound to 127.0.0.1 + tailscale serve only, so they had no LAN entry point at all). This adds a local, internet-independent path while keeping Tailscale for remote.
Local DNS — wildcard on telep-router
A wildcard address record was added to dnsmasq on telep-router so every *.telep.lan name resolves to the mainframe (192.168.1.123):
uci add_list dhcp.@dnsmasq[0].address='/telep.lan/192.168.1.123'
uci commit dhcp
/etc/init.d/dnsmasq restartLAN clients pick this up automatically because the router is their DHCP-advertised DNS server. Verified: files.telep.lan, kraken.telep.lan, and arbitrary *.telep.lan names all resolve to .123.
AAAA is NXDOMAIN — this is cosmetic
The wildcard is an A-record only; AAAA lookups return NXDOMAIN. IPv6 is disabled on the LAN anyway (see IPv6 disabled on the LAN (2026-07-28)) so the A-record path is all that matters.
dnsmasq change — mind the duplicate-reservation footgun
Any dnsmasq edit on this router restarts the daemon. A bad config = site-wide DHCP+DNS outage. This change was made the same session as (and separate from) the duplicate dhcp-host outage — always verify dnsmasq restarts cleanly after committing.
Reverse proxy — Caddy on telep-mainframe
Caddy v2.11.4 installed from the official Caddy apt repo (cloudsmith caddyserver/stable).
The cloudsmith auto-config produced a broken repo URL on Debian trixie
The auto-generated
config.deb.txtemitted anany-distro/any-versionURL that 404’d on trixie. Correct the repo path to:deb https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main
- systemd unit +
/etc/caddy/Caddyfile(original backed up as.orig). - Listens on
*:80, withauto_https offso Caddy NEVER tries to obtain a Let’s Encrypt cert for the non-public.landomain. - Left untouched: Tailscale
serve(9 proxies) and all 7 docker containers. Caddy is purely additive.
Name → backend map
All entries are HTTP on :80, verified 200 end-to-end unless noted.
| Name | Backend | Notes |
|---|---|---|
telep.lan / home.telep.lan | 127.0.0.1:3010 | now the Homepage status dashboard (was inline HTML; old block backed up /etc/caddy/Caddyfile.bak-home-dash) |
files.telep.lan | 127.0.0.1:8334 | filebrowser |
frigate.telep.lan | https://127.0.0.1:8971 | TLS backend, self-signed → tls_insecure_skip_verify |
kraken.telep.lan | 192.168.1.200:8080 | the Pi — 502 while the Pi is offline, entry is correct |
top.telep.lan | 127.0.0.1:8090 | top4-web / Top képek |
print.telep.lan | 127.0.0.1:8095 | label printer editor |
whiteboard.telep.lan | 127.0.0.1:8790 | tldraw board |
ruview.telep.lan | 127.0.0.1:3000 | needs header_up Host {upstream_hostport} (backend 421’d otherwise) |
go2rtc.telep.lan | 127.0.0.1:1984 | |
jellyfin.telep.lan | 127.0.0.1:8096 | ⚠️ guessed name, backend down — flagged for removal/rename |
Two config gotchas worth remembering
- frigate speaks HTTPS with a self-signed cert on
:8971→ the upstream needstls_insecure_skip_verify.- ruview returned HTTP 421 Misdirected Request until
header_up Host {upstream_hostport}was added (its DNS-rebinding Host-header validation, same family of issue as itsSENSING_ALLOWED_HOSTScheck — see 2026-08-11-ruview-esp32-csi-real-hardware).
Deliberately NOT proxied
Not in tailscale serve and/or not browsable UIs: stirling-pdf (:8080), qdrant (:6333/:6334), knowledgebase (:8092), home-portal (:8093), ruview alt (:3001), frigate unauth (:5000).
Caddy boot-race outage (2026-08-17)
All
*.telep.lan+ bothlevandor.ioportals were down by-domain for ~1.6 days
caddy.servicehad beenfailedsince 2026-08-15 18:44 — since the YubiKey-FDE reboots. It went unnoticed because all that work was over console/ssh, never by domain.
Discovery. While wiring the home dashboard into Caddy, systemctl status caddy showed failed with:
listening on 192.168.1.123:443: bind: cannot assign requested address
Root cause. Caddy starts at boot before the LAN IP 192.168.1.123 is assigned to enp5s0, fails to bind :443, and does not retry — so it stayed dead. The bind 192.168.1.123 on the :443 blocks (needed to avoid colliding with Tailscale’s 100.115.209.87:443 — see 2026-08-15-admin-portal-passkey-olivetin) is exactly what makes it sensitive to the IP not being up yet.
Impact. Every *.telep.lan service and both levandor.io portals (admin.levandor.io, id.levandor.io) were unreachable-by-domain the whole time. Backends were fine; only the domain front door was gone.
Fix (applied).
net.ipv4.ip_nonlocal_bind=1— the real fix for the race; lets Caddy bind an address before it is assigned. Persisted in/etc/sysctl.d/99-caddy-nonlocal-bind.conf.- systemd drop-in
/etc/systemd/system/caddy.service.d/resilience.conf— belt-and-suspenders:Restart=on-failure,RestartSec=5,Wants=network-online.target,After=network-online.target.
After systemctl start caddy: home.telep.lan → 200, admin.levandor.io → 302. Also restarted oauth2-proxy — admin.levandor.io was 502 because that container was down too. Runbook: caddy-boot-race.
Result
Home or away, internet or not, every service is reachable by a stable *.telep.lan name. Tailscale remains the remote path.
Related
- 2026-08-17-home-dashboard — the Homepage status dashboard now proxied at
home.telep.lan; its build surfaced the boot-race - caddy-boot-race — runbook for the “all domains down after a reboot” bind-race
- 2026-08-15-yubikey-gated-luks-fde — the reboots that triggered the race
- telep-mainframe — the host running Caddy + all the backends
- telep-router — the OpenWrt router serving the
*.telep.lanwildcard DNS - 2026-08-15-dhcp-outage-duplicate-reservation-postmortem — same-session dnsmasq outage; the internet-independence this note adds is partly motivated by such failures
- tailnet-service-exposure-convention — the complementary remote-exposure convention (dedicated tagged node per service)
- 2026-08-11-ruview-esp32-csi-real-hardware — the ruview Host-header validation that also bit the reverse proxy