Treating Traefik Host() labels as the only hostname inventory is the ops habit that keeps a homelab edge from rotting. I split public vs mesh traffic by entrypoint rather than inventing a second naming scheme — one entrypoint for TLS-facing routers, another for VPN-only names — so a new compose service either gets a public CNAME or stays internal without a hand-edited DNS sheet. When a router also carries PathPrefix, health checks should hit that path on the same hostname the Host rule advertises; a monitor aimed at / while the app only answers under /api quietly marks a healthy stack as down.
After a label change I confirm which router and entrypoint actually matched, that the public name’s A/AAAA or tunnel target still lands on this edge, and that retired Host() values no longer linger in DNS or status pages. Compound Host() || Host() rules need every hostname provisioned and later cleaned; HostRegexp is fine for routing but cannot drive a static record, so I keep those routers off any auto-DNS path. A deploy that leaves orphan CNAMEs or monitors for containers you removed months ago is usually label drift, not a Traefik crash.