Public: anyone can read this; nobody can change it.
Private plane: self-hosted Headscale mesh for operator access + fleet (MagicDNS), de-coupling admin from Cloudflare #96
Sign in to join this conversation.
Public: anyone can read this; nobody can change it.
Two-plane edge: public serving is open ports + ACME; private is a self-hosted mesh (Headscale)
Deciding the domain data-plane surfaced a clean split the platform should adopt. Public serving of client apps + their own domains must go through a public entrypoint (VPS 80/443 + cert-manager HTTP-01) — there's no VPN escape from that (a client's end-users aren't on any mesh). That work is tracked separately (BYO-domains). This issue is the private plane.
What Headscale is (and isn't) for here
Headscale = self-hosted, open-source Tailscale control server (WireGuard mesh + MagicDNS). It is the right tool for private connectivity, NOT public serving:
*.ts.netwith a Tailscale cert (same custom-domain wall as the Cloudflare tunnel), and Headscale has no production Funnel. MagicDNS resolves only inside the tailnet.Why adopt it (open-standard, de-couples from Cloudflare)
ssh + port-forward. Today the granddaughter is administered viassh root@droplet+kubectl port-forward— a mesh replaces that withforgejo.<tailnet>/ direct apiserver access, private by default.Scope (design first)
Acceptance
An operator administers a platform (Forgejo + kubectl + a dashboard) entirely over the Headscale tailnet with those surfaces NOT publicly reachable; a second node joins the mesh and reaches internal services by MagicDNS; documented.
Filed from the domain-data-plane design session, 2026-07-08. Design-only until the BYO-domain public-plane work lands.