<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>Gateway-API on Fuchsbau</title>
    <link>https://this-is-fine.io/tags/gateway-api/</link>
    <description>Recent content in Gateway-API on Fuchsbau</description>
    <image>
      <title>Gateway-API on Fuchsbau</title>
      <link>https://this-is-fine.io/tags/gateway-api/</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:11 UT</lastBuildDate>
    <atom:link href="https://this-is-fine.io/tags/gateway-api/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Envoy Gateway and the Move from Traefik to Gateway API</title>
      <link>https://this-is-fine.io/posts/20251122-envoy-gateway-headscale-routes/</link>
      <pubDate>Sat, 22 Nov 2025 08:00:00 UT</pubDate>
      <dc:creator>ff0x</dc:creator>
      <guid>https://this-is-fine.io/posts/20251122-envoy-gateway-headscale-routes/</guid>
      <description>The lab used to run Traefik with its own CRDs (IngressRoute, Middleware, and friends). Gateway API standardises routes; Envoy Gateway is the controller here — one Helm install, three shared Gateways, and per-app HTTPRoute resources instead of Traefik-only objects.
Traefik is excellent at the edge, but its CRDs are controller-specific. Moving to Gateway API was less about feature envy and more about portability: the same HTTPRoute can be read by another implementation if you ever switch controllers. Envoy Gateway is the implementation here; the routes stay standard Kubernetes objects.
</description>
      <category domain="https://this-is-fine.io/categories/infrastructure">Infrastructure</category>
      <content:encoded><![CDATA[The lab used to run Traefik with its own CRDs (IngressRoute, Middleware, and friends). Gateway API standardises routes; Envoy Gateway is the controller here — one Helm install, three shared Gateways, and per-app HTTPRoute resources instead of Traefik-only objects.
Traefik is excellent at the edge, but its CRDs are controller-specific. Moving to Gateway API was less about feature envy and more about portability: the same HTTPRoute can be read by another implementation if you ever switch controllers. Envoy Gateway is the implementation here; the routes stay standard Kubernetes objects.
Traefik habits vs Gateway API Traefik Gateway API IngressRoute &#43; entrypoints HTTPRoute &#43; parentRefs on a Gateway listener Per-app TLS / middleware CRDs TLS on the Gateway; filters on HTTPRoute; Envoy policies when needed Traefik host rules hostnames and matches on gateway.networking.k8s.io/v1 Routes stay portable across controllers. Envoy-specific tuning uses gateway.envoyproxy.io (BackendTrafficPolicy, ClientTrafficPolicy, &amp;hellip;).
Three shared gateways Envoy Gateway (Helm) shared-gateway-external *.this-is-fine.io, *.this-is-fine.social Let&amp;#39;s Encrypt, LB .0.1 shared-gateway-internal *.this-is-fine.internal Vault PKI, LB .0.2 shared-gateway-tailnet *.tif.internal Vault PKI, LB .0.3 Pick the gateway by who connects: the internet, lab browsers on the internal CA, or tailnet clients. Templates under k8s/templates/gateway-api/ repeat the same HTTPRoute shape for each class.
Static LoadBalancer IPs (.0.1, .0.2, .0.3) come from a small pool advertised with Cilium BGP. DNS and certificates differ per zone, but the dataplane pattern is the same: one Envoy deployment, several logical gateways, many HTTPRoutes attached to listeners.
Headscale example (public API, private UI) Headscale disables Helm ingress; exposure is all Gateway API.
Surface Hostname Gateway Backend Tailscale clients / API ts.this-is-fine.io shared-gateway-external :8080 Web UI (operators) ts.this-is-fine.internal shared-gateway-internal :8081 (UI sidecar) The external route allows CORS from https://ts.this-is-fine.internal. Control traffic needs WebSocket upgrades; a BackendTrafficPolicy on that HTTPRoute enables tailscale-control-protocol and derp.
Splitting API and UI across external and internal DNS is deliberate. Tailscale clients and the public internet need ts.this-is-fine.io with a certificate browsers and devices trust. Operators can open the same logical service on ts.this-is-fine.internal with the lab’s internal CA, without publishing the admin UI to the open internet.
Public API (lab pattern):
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: headscale-https-external spec: parentRefs: - name: shared-gateway-external namespace: envoy-gateway-system sectionName: this-is-fine-io-https hostnames: - ts.this-is-fine.io rules: - backendRefs: - name: headscale port: 8080 Internal UI — same host label on the internal zone, different listener and port:
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: headscale-ui-https-internal spec: parentRefs: - name: shared-gateway-internal namespace: envoy-gateway-system sectionName: this-is-fine-internal-https hostnames: - ts.this-is-fine.internal rules: - backendRefs: - name: headscale port: 8081 Helm sets HEADSCALE_SERVER_URL=https://ts.this-is-fine.io so clients and the UI agree on the public URL while operators open the UI on the internal name.
TODO: connect Pocket ID for Headscale OIDC (HEADSCALE_OIDC_* is stubbed in chart values; not enabled yet). Same backlog as Zeroclaw UI and Vault.
Adding another app Expose the workload with a Service. Attach an HTTPRoute (or TCPRoute) to the right shared-gateway-* and hostname. Let cert-manager issue TLS via the gateway certificateRefs / ClusterIssuers. IRC on port 6697 uses TCPRoute on the public gateway — IRC post. VIPs .0.1–.0.3 are advertised with Cilium BGP. GitOps context: lab overview.
]]></content:encoded>
    </item>
    <item>
      <title>IRC in the Lab: InspIRCd and a ZNC Bouncer</title>
      <link>https://this-is-fine.io/posts/20251121-irc-inspircd-znc/</link>
      <pubDate>Fri, 21 Nov 2025 10:00:00 UT</pubDate>
      <dc:creator>ff0x</dc:creator>
      <guid>https://this-is-fine.io/posts/20251121-irc-inspircd-znc/</guid>
      <description>IRC is still a simple model: one server, many channels, text over a long-lived TCP session. InspIRCd runs the network; ZNC is a bouncer that stays logged in when your client disconnects and replays backlog when you return.
In the lab both are plain Deployments under Flux, with TLS from cert-manager and a Gateway API TCPRoute for TLS on port 6697.
IRC is a good contrast to HTTP-only homelab apps: clients expect a long-lived TCP session and often TLS on a non-443 port. Gateway API TCPRoute covers that without bolting IRC into an HTTP ingress controller as a special case.
</description>
      <category domain="https://this-is-fine.io/categories/infrastructure">Infrastructure</category>
      <content:encoded><![CDATA[IRC is still a simple model: one server, many channels, text over a long-lived TCP session. InspIRCd runs the network; ZNC is a bouncer that stays logged in when your client disconnects and replays backlog when you return.
In the lab both are plain Deployments under Flux, with TLS from cert-manager and a Gateway API TCPRoute for TLS on port 6697.
IRC is a good contrast to HTTP-only homelab apps: clients expect a long-lived TCP session and often TLS on a non-443 port. Gateway API TCPRoute covers that without bolting IRC into an HTTP ingress controller as a special case.
Traffic path IRC client (TLS, port 6697) -&amp;gt; znc.this-is-fine.io (Envoy TCPRoute) -&amp;gt; ZNC (state on PVC) -&amp;gt; InspIRCd (same namespace) Daemon Docs Role InspIRCd docs.inspircd.org Channels, users, server links ZNC wiki.znc.bz Persistent session and backlog InspIRCd owns the network name and channels. ZNC sits in front for humans: you connect to ZNC with your IRC client, ZNC stays connected to InspIRCd, and you can disconnect overnight without losing channel context. Only the bouncer needs a PVC; the IRC daemon can stay ephemeral apart from config secrets.
TLS and gateways Port 6697 is the usual TLS IRC port (IRCS). The public bouncer uses an Envoy TCP listener and a cert-manager certificate for znc.this-is-fine.io. An optional admin UI, if enabled, sits on *.this-is-fine.internal like other lab apps — see the DNS overview.
Operator and bridge passwords are SOPS-encrypted in Git.
Extras ZNC data can use the VolSync &#43; restic template like any PVC-backed app. An optional Tor sidecar exists in Git for alternate exposure. Deeper setup: InspIRCd configuration wiki, ZNC setup guide.
]]></content:encoded>
    </item>
    <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>
