Every *.telep.lan service and both levandor.io portals (admin, id) are unreachable by domain after a reboot — but the backends themselves are fine. Cause: Caddy started at boot before the LAN IP 192.168.1.123 was assigned, failed to bind :443, and did not retry, so it stayed dead. Discovered 2026-08-17 after it had been down ~1.6 days (since the YubiKey-FDE reboots on 2026-08-15). Full incident: Caddy boot-race outage (2026-08-17).
This is a single-service, site-wide outage
One dead host service (
caddy.serviceon telep-mainframe) takes down all domain-based access at once —home.telep.lan,files.telep.lan,frigate.telep.lan,admin.levandor.io,id.levandor.io, everything. It fails silently: nothing alarms, and it is easy to miss if all your work is over ssh / the console (which is exactly how the YubiKey reboots were done). Thehome.telep.landashboard’s tailnet path (telep-mainframe.taild4189d.ts.net:8450) still works because it bypasses Caddy — 2026-08-17-home-dashboard.
Symptoms
- Nothing on
*.telep.lanloads by name; bothadmin.levandor.ioandid.levandor.ioare dead. - DNS still resolves (
nslookup files.telep.lan→192.168.1.123) and the backends are up if hit directly. - Just after a reboot (especially the YubiKey-gated boots — see 2026-08-15-yubikey-gated-luks-fde).
Diagnose
On the mainframe (ssh levander@100.115.209.87 if the LAN name is dead):
systemctl status caddy # look for: failed (Result: exit-code)
journalctl -u caddy -b | tail # THE tell:
# listening on 192.168.1.123:443: bind: cannot assign requested addressThat bind error = Caddy came up before enp5s0 had 192.168.1.123. The bind 192.168.1.123 on the :443 blocks (needed so it doesn’t collide with Tailscale’s 100.115.209.87:443, see 2026-08-15-admin-portal-passkey-olivetin) is what makes Caddy sensitive to the IP not being up yet.
Fix (immediate)
sudo systemctl start caddy
# verify:
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: home.telep.lan' http://127.0.0.1/ # 200
curl -s -o /dev/null -w '%{http_code}\n' https://admin.levandor.io/ -k # 302Also check oauth2-proxy —
admin.levandor.iocan be 502 even with Caddy upDuring this incident the
oauth2-proxycontainer was also down, soadmin.levandor.ioreturned 502 after Caddy came back.cd /home/levander/admin-portal && docker compose up -d oauth2-proxy(or--force-recreate). See 502-after-auth.
Permanent fix (already applied 2026-08-17)
Two layers so this can never recur:
net.ipv4.ip_nonlocal_bind=1— the real fix for the race; lets Caddy bind an address before it is assigned to the interface. Persisted:# /etc/sysctl.d/99-caddy-nonlocal-bind.conf net.ipv4.ip_nonlocal_bind = 1- systemd drop-in
/etc/systemd/system/caddy.service.d/resilience.conf— belt-and-suspenders retry + ordering:[Unit] Wants=network-online.target After=network-online.target [Service] Restart=on-failure RestartSec=5
Quick mental model
All
.telep.lan/levandor.iodown after a reboot →systemctl status caddyfor the:443bind race. Fix =ip_nonlocal_bind=1(already persisted) +systemctl start caddy; if still 502, also bring upoauth2-proxy.
Related
- 2026-08-15-telep-lan-split-horizon-caddy — the
:80+:443Caddy design; hosts the full boot-race incident write-up - telep-mainframe — the host; boot-race banner in Caddy :443 boot-race
- 2026-08-17-home-dashboard — the status dashboard whose build surfaced this; its tailnet path survives a Caddy outage
- 2026-08-15-yubikey-gated-luks-fde — the reboots that triggered the race
- admin-portal-login-broken —
admin.levandor.io-specific failures (the 502 after Caddy recovers) - service-unreachable — the general per-service “won’t load” runbook
- runbooks-index — all homelab runbooks