Skip to content

Exposure

Every service is LAN-only by default: the Cloudflare wildcard *.madhan.app points at the private Gateway IP. A service becomes public only when it is listed in publicServices in cloudflare.go.

flowchart LR
  subgraph DNS[Cloudflare, DNS-only]
    W["*.madhan.app → 192.168.1.220"]
    P["public names → 178.156.199.250"]
  end
  W --> G[Cilium Gateway]
  P --> T[Traefik on Bifrost] -->|ForwardAuth unless SkipAuth| N[NetBird tunnel] --> G

All records are DNS-only (not proxied). A specific record beats the wildcard, so deleting a service’s record is all it takes to make it private again: its name falls back to 192.168.1.220, which the internet cannot reach.

Name or addressLANVPN (NetBird)Public
auth, netbird, uptime, proxy, *.proxyYesYesYes, served by Bifrost itself
grafanaYesYesYes, Grafana’s own Authentik login (SkipAuth: true)
argocd, hubble (Pulumi HTTPRoutes)YesYesNo
longhorn, openbao, harbor, n8n, headlamp, falco, vmselect, alertmanager, victorialogs, kubeflow, ollama, comfyuiYesYesNo
192.168.1.225:11434 (Ollama LoadBalancer)YesYesNo
192.168.1.230 (CS2 LoadBalancer)YesYesNo

Hostnames are <name>.madhan.app. VPN reach comes from the 192.168.1.0/24 route that k8s-routing-peer advertises to the All group; the public wildcard record makes the same names resolve off-LAN. ComfyUI ships scaled to zero.

  1. Add it to publicServices in cloudflare.go. Set SkipAuth: true only if the app does its own Authentik login.

    core/cloud/cloudflare.go
    var publicServices = []PublicService{
    {Name: "grafana", SkipAuth: true},
    {Name: "headlamp"},
    }
  2. Run just core hetzner up. It regenerates traefik/dynamic/public-services.yml (gitignored) and Traefik hot-reloads the router.

  3. Run just core cloudflare up to create the A record pointing at 178.156.199.250.

  4. Check: dig +short headlamp.madhan.app returns 178.156.199.250, and an unauthenticated curl -I https://headlamp.madhan.app redirects to auth.madhan.app.

To make it private again, remove the entry and run the same two commands. Never edit public-services.yml or services.yml for this; the first is regenerated on every run.

netbird expose <port> from any mesh peer publishes <name>.proxy.madhan.app through Traefik TCP passthrough and netbird-proxy, without DNS changes and without Authentik. See NetBird.

A service is still public after removing it

Section titled “A service is still public after removing it”

The A record still exists: run just core cloudflare up. Resolvers may cache the old answer until its TTL expires.

Traefik has the route but cannot reach the Gateway. See Bifrost troubleshooting.