Domain routing repair — 2 November 2026

Scope and result

Checked 14 AdGuard .local names and 27 public homelab hostnames, deduplicated from live DNS, NPM and tunnel configuration. Also inspected the remaining explicit public DNS entries: ring, two test names, and externally hosted ai/www. No DNS records were deleted.

Final server-side checks: 13/14 local names have working app/API routes; 25/27 public app origins respond from both the main server and the Pi. All 26 public subdomains retain the observed Cloudflare Access redirect. The apex returns Home Assistant HTTP 200. An Access redirect is not an authenticated browser/app acceptance test.

Confirmed faults and repairs

  • Main and standby homelab tunnel configurations disagreed. Reconciled to the same 33 hostname/path rules while preserving private prefixes and using connector-appropriate origin addresses.
  • Five existing DNS records (apex, home, doorbell, frigate, mealie) targeted a separate HA-app tunnel. Repointed them to homelab and read each record back through Cloudflare’s API.
  • The redundant Supervisor Cloudflared app contained unreachable localhost origins and could reclaim those DNS records at startup. Set its boot mode to manual, stopped it, and verified both values. Left its configuration installed for rollback. The standalone Pi homelab connector remains running.
  • ha.local and ha-mcp.local incorrectly resolved to the Pi’s port 80, bypassing NPM. Updated both AdGuard rewrites to 192.168.0.182 and verified actual DNS replies and routes.
  • NPM’s Open Notebook alias forwarded to 127.0.0.1 inside the NPM container. Corrected to 192.168.0.182:8502 and added that already-configured alias consistently to homelab ingress.
  • Vaultwarden is mounted at /vault/. Added an exact-root relative redirect in NPM for the existing local/public aliases; confirmed the landing route returns 200. No authentication or signup setting changed.

Verification

  • Nginx configuration test passed.
  • Both Cloudflared proposals passed ingress validation before deployment.
  • Read live main-connector configuration and standby file back; confirmed exact hostname/path pair equality and main origin-target equality.
  • Retested every listed local and public app origin, including from the Pi.
  • Independently stopped each homelab connector for a short test, restoring it in a finally block. Apex / and /vault/ both returned 200 through Cloudflare with only the main connector, and with only the Pi connector.
  • Both homelab connectors were running after the final test.

Remaining boundaries and blockers

  • n8n.local and n8n.00000041.xyz: no deployed n8n container or listener on 5678; the historical host Compose directory is absent. The n8nn_n8n_data volume remains. Restoring an application needs an explicit restore-vs-retire decision and recovery validation, not a DNS edit.
  • decent.00000041.xyz: no listener on 8653. The maintained recovery runbook already records the old visualiser source as missing. No replacement was invented or deployed.
  • hermes.local is an API, not a web homepage: /health returns 200; its root 404 is expected for the current service. HA MCP rejects an unauthorised root request with 403; that is not a routing failure.
  • ring and the two test DNS names have no matching ingress on either homelab connector. Their anonymous requests show Access before the origin, not proof of a working app. Left intact pending an intentional keep/retire decision. ai and www target external hosting and were not reconfigured.
  • This server still uses Virgin DNS rather than AdGuard for its normal resolver. A normal getent lookup of a .local name exceeded a five-second bound, while all explicit AdGuard lookups worked. Clients must use 192.168.0.182 for these names; host/router DNS changes require the appropriate admin action. .local also conflicts with mDNS on some clients.
  • Existing apex /home legacy path returns 404 at the dashboard origin; restored its existing rule without inventing a rewrite or moving dashboard assets onto Home Assistant’s root.
  • Protected API path rules were preserved and restored consistently. Unauthenticated GET status checks are not full authorised protocol tests; no authenticated API success is claimed.

Attribution and rollback

The clobbered main config’s recorded modification time was 1 November at 20:17:31, not proof of a change by Beetroot today. The separate HA app started on 2 November and its logs contain actual refused Frigate-origin connections. No actor attribution is established.

Private rollback snapshots and final JSON evidence: /home/joe/.hermes/backups/domain-repair-20261102/. Plan: .hermes/plans/2026-11-02_231701-local-domains.md.

Rollback is per-component: restore saved tunnel YAML with readable container permissions and validate/restart one connector at a time; restore only the five saved DNS targets via their record IDs; use saved NPM host JSON and AdGuard rewrite snapshots for API patches. The duplicate HA app can be set back to auto/start via Supervisor, but doing so can reclaim DNS; restore its intended DNS ownership deliberately rather than starting it blindly.