<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>Cert-Manager on Fuchsbau</title>
    <link>https://this-is-fine.io/tags/cert-manager/</link>
    <description>Recent content in Cert-Manager on Fuchsbau</description>
    <image>
      <title>Cert-Manager on Fuchsbau</title>
      <link>https://this-is-fine.io/tags/cert-manager/</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/cert-manager/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>
  </channel>
</rss>
