<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <docs>https://blogs.law.harvard.edu/tech/rss</docs>
    <title>Tailscale on Fuchsbau</title>
    <link>https://this-is-fine.io/tags/tailscale/</link>
    <description>Recent content in Tailscale on Fuchsbau</description>
    <image>
      <title>Tailscale on Fuchsbau</title>
      <link>https://this-is-fine.io/tags/tailscale/</link>
      <url>https://source.unsplash.com/2000x1322/?fox</url>
    </image>
    <ttl>1440</ttl>
    <generator>Hugo 0.125.4</generator>
    <language>de-DE</language>
    <lastBuildDate>Wed, 20 May 2026 22:26:12 UT</lastBuildDate>
    <atom:link href="https://this-is-fine.io/tags/tailscale/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Cluster-Wide Tailscale: Headscale, Tailnet DNS, and Cross-Cluster Routes</title>
      <link>https://this-is-fine.io/posts/20251121-tailscale-headscale-mesh/</link>
      <pubDate>Fri, 21 Nov 2025 09:00:00 UT</pubDate>
      <dc:creator>ff0x</dc:creator>
      <guid>https://this-is-fine.io/posts/20251121-tailscale-headscale-mesh/</guid>
      <description>Tailscale builds a WireGuard mesh with little configuration. Headscale is an open control server for the same clients — you run policy and issue keys yourself. The lab does not use the Tailscale Kubernetes operator; a handful of Deployments and DaemonSets do the job instead.
The goal is one tailnet for laptops and nodes, with Kubernetes APIs and internal HTTP on *.tif.internal without putting those names on the public internet.
Self-hosting the control plane means you own ACL files, preauth keys, and MagicDNS base domains. The trade-off is operational work: upgrades, backups, and policy edits are yours. For a multi-cluster lab that already runs GitOps everywhere else, that trade-off is acceptable.
</description>
      <category domain="https://this-is-fine.io/categories/infrastructure">Infrastructure</category>
      <content:encoded><![CDATA[Tailscale builds a WireGuard mesh with little configuration. Headscale is an open control server for the same clients — you run policy and issue keys yourself. The lab does not use the Tailscale Kubernetes operator; a handful of Deployments and DaemonSets do the job instead.
The goal is one tailnet for laptops and nodes, with Kubernetes APIs and internal HTTP on *.tif.internal without putting those names on the public internet.
Self-hosting the control plane means you own ACL files, preauth keys, and MagicDNS base domains. The trade-off is operational work: upgrades, backups, and policy edits are yours. For a multi-cluster lab that already runs GitOps everywhere else, that trade-off is acceptable.
Read first Piece Docs Headscale headscale.net Talos Tailscale extension Talos network guide Gateway API gateway-api.sigs.k8s.io Envoy Gateway gateway.envoyproxy.io Public control plane URL: ts.this-is-fine.io. MagicDNS suffix: tif.internal.
What joins the mesh Headscale (ts.this-is-fine.io) Talos nodes (Tailscale extension) kube-apiserver-proxy per cluster (TCP 6443 on tailnet) tailnet-dns (pods resolve *.tif.internal) address space: 100.64.0.0/10 kube-apiserver-proxy runs tailscaled and socat. Tailnet clients use hydra-k8s.tif.internal:6443 (pattern: &amp;lt;cluster&amp;gt;-k8s.tif.internal) to reach the cluster API VIP. tailnet-dns forwards *.tif.internal to Headscale MagicDNS from inside the cluster.
Pods do not run a Tailscale sidecar in this design. Workloads that need the Kubernetes API or an internal service use cluster DNS first. The tailnet-dns DaemonSet patches the chain so *.tif.internal resolves the same way your laptop would on the mesh. Egress from the pod still leaves via the node’s tailnet identity, so ACLs must allow that path.
HTTP on the tailnet Attach an HTTPRoute to shared-gateway-tailnet. Example hostname: vault.tif.internal -&amp;gt; Envoy -&amp;gt; Service. TLS comes from in-cluster PKI via cert-manager.
tailnet client (HTTPS) -&amp;gt; vault.tif.internal -&amp;gt; shared-gateway-tailnet -&amp;gt; Service -&amp;gt; Pods Public sites use a different gateway (this-is-fine.io, Let&amp;rsquo;s Encrypt). Keep listeners separate so you do not accidentally expose an internal-only app.
Policy (sketch) Headscale ACLs use tags (k8s-api, fabric, per-cluster node tags) and auto-approved routes for the LoadBalancer slice that fronts the tailnet gateway. Join keys are SOPS-encrypted bootstrap secrets.
Operator UI: ts.this-is-fine.internal on port 8081 through the internal gateway.
Part of the wider GitOps lab. IRC TLS on the public gateway is covered in the IRC post.
]]></content:encoded>
    </item>
  </channel>
</rss>
