15168
Cloud Computing

Automating DNS and Monitoring for Traefik: A Q&A Guide

Managing DNS records and monitoring for every service in a Traefik homelab often means juggling multiple systems manually. Each container's hostname is defined once in a Docker label but never propagates to Cloudflare, NetBird, or Uptime Kuma. traefik-mesh-companion turns this around by making the container definition the single source of truth and automatically syncing the rest. Below we answer common questions about how this sidecar works.

# What problem does traefik-mesh-companion solve?

Every time you add a new container with a Traefik Host() rule, you used to have to manually update Cloudflare for public DNS, NetBird for internal VPN hostnames, and Uptime Kuma for monitoring—each with its own groups, tags, and status pages. Removing a container four months later meant those stale records stayed unless you remembered to clean them up. This manual process is error‑prone and wasteful. traefik-mesh-companion eliminates this duplication by reading the existing Traefik labels from the Docker socket and pushing the information to all three services automatically. The container definition becomes the single source of truth, so adding or removing a service updates DNS and monitoring in one step.

Automating DNS and Monitoring for Traefik: A Q&A Guide
Source: dev.to

# How does the tool automatically sync DNS records?

The companion is a Go sidecar that watches the Docker socket. It reads every container's Traefik routing labels—specifically the Host() rules and entrypoint assignments. Based on two environment variables (INTERNAL_FILTER and EXTERNAL_FILTER), it decides where to send each hostname. Routers on an entrypoint matching INTERNAL_FILTER go to NetBird for mesh VPN DNS; those matching EXTERNAL_FILTER go to Cloudflare as A records or CNAMEs pointing to a Cloudflare Tunnel. The tool also pushes monitor configurations to Uptime Kuma (and optionally Gatus) using the same rule‑derived information. This happens continuously, so any change to a container's labels is reflected within seconds.

# How does split-horizon DNS work with entrypoints?

Split‑horizon DNS allows the same hostname to resolve to different IPs inside your home network and on the public internet. traefik-mesh-companion implements this using your existing Traefik entrypoint labels. You define two filters: INTERNAL_FILTER=internal and EXTERNAL_FILTER=https. Any router whose entrypoint is internal will be synced only to NetBird; routers with entrypoint https go only to Cloudflare. No extra labels are needed—your current Traefik configuration stays unchanged. For example, a dashboard with entrypoints: internal becomes a private NetBird hostname, while an API with entrypoints: https gets a public Cloudflare record. If you need to override, per‑container labels like mesh.dns.internal: "false" can exclude a container from the internal pipeline.

# How does the rule parser extract hostnames from Traefik rules?

Traefik rules can be complex, combining multiple Host() matchers with &&, ||, and PathPrefix(). The companion uses a pure‑Go regex AST to parse them. For compound rules like (Host(`a.example.com`) || Host(`b.example.com`)) && PathPrefix(`/v2`), it extracts both hostnames for DNS and captures the PathPrefix separately for building monitor URLs. HostRegexp rules are intentionally skipped because a dynamic pattern cannot be translated into a static DNS record. This ensures that only concrete, resolvable hostnames are synced, avoiding broken records from patterns like HostRegexp(`{subdomain:[a-z]+}.example.com`).

Automating DNS and Monitoring for Traefik: A Q&A Guide
Source: dev.to

# How can I customize monitoring settings per router?

The tool introduces a mesh.routers.* label namespace that lives outside Traefik’s schema validator, so you can freely add monitoring properties. The hierarchy of fallback works like this: mesh.routers.<router_name>.kuma.<property> has the highest priority, then mesh.routers.<router_name>.<property>, then mesh.kuma.<property>, and finally mesh.<property>. For example, you can set a custom health endpoint with mesh.routers.api.kuma.url: "/health", override accepted status codes with mesh.routers.api.kuma.accepted_status_codes: "200, 204", and define group tags and status pages at the global mesh.kuma.tags level. This flexible system lets you fine‑tune monitoring without breaking Traefik’s own label validation.

# What providers are supported for DNS and monitoring sync?

Currently the companion supports three main endpoints. For internal mesh VPN DNS it syncs to NetBird. For public DNS it pushes A records or CNAMEs to Cloudflare (typically pointing to a Cloudflare Tunnel). For monitoring it syncs monitors, groups, tags, and status pages to Uptime Kuma. Additionally, there is a Gatus Bridge option that can push endpoints and groups to Gatus. All of this is handled from a single Docker Compose sidecar—no Kubernetes, Helm, or operator required. The design intentionally keeps the list of providers small to remain lightweight, but the architecture is modular enough that new providers could be added in the future.

# Can I exclude specific containers or routers from syncing?

Yes. The companion respects per‑container overrides. To exclude a container entirely from the internal pipeline, set the label mesh.dns.internal: "false". To exclude a specific router from all syncing (DNS and monitoring), use mesh.routers.admin.managed: "false". These overrides are checked after the automatic filter logic, giving you fine‑grained control. For example, you might want a container to be reachable via NetBird but not exposed to Cloudflare, or you might have a temporary router that should not create any monitors. The fallback hierarchy ensures that explicit false values always win, so you never accidentally push unwanted records.

💬 Comments ↑ Share ☆ Save