From 1714b99b715cdfa4863f8e04476b261e1f0bf3cf Mon Sep 17 00:00:00 2001 From: rock Date: Sat, 31 Oct 2026 15:10:21 -0700 Subject: [PATCH] feat(cloudflared): publish the kube-apiserver at k8s.riotpiao.com Adds a tunnel ingress rule so kubectl works from outside the LAN now that the apiserver authenticates against ZITADEL. Two deliberate details: 1. The origin is the in-cluster Service (kubernetes.default.svc.cluster.local:443), not a node IP. That survives a control-plane address change and lets each connector reach a local-healthy apiserver. 2. originRequest.noTLSVerify is required. The apiserver presents a certificate for the cluster CA plus its node addresses, so its SANs cannot match this public hostname. Cloudflare terminates the public TLS with the *.riotpiao.com edge certificate and the connector hop is already inside the cluster, so skipping verification on that short hop is the least-bad option. This is scoped to this one rule; do not copy it elsewhere. The hostname is served on 443. Cloudflare Tunnel hostname rules do not proxy arbitrary ports, so kubeconfig must use https://k8s.riotpiao.com with no :6443. SECURITY: this exposes the Kubernetes API to the internet. Authentication is still ZITADEL OIDC plus client certificates, but a Cloudflare Access application belongs in front of the hostname. That is a separate change and is not included here. --- k8s/apps/cloudflared/configmap.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/k8s/apps/cloudflared/configmap.yaml b/k8s/apps/cloudflared/configmap.yaml index 656469c..138d416 100644 --- a/k8s/apps/cloudflared/configmap.yaml +++ b/k8s/apps/cloudflared/configmap.yaml @@ -53,4 +53,25 @@ data: # even though the DNS CNAME points at the tunnel. - hostname: zitadel.riotpiao.com service: https://zitadel.riotpiao.com + # KUBERNETES API, for kubectl from outside the LAN. + # + # Origin is the in-cluster Service, not the node IP: that survives a + # control-plane address change and lets the connectors reach whichever + # apiserver is local-healthy. + # + # noTLSVerify is required. The apiserver serves a certificate for the + # cluster CA plus its node/LB addresses, so its SANs cannot match this + # public hostname. Cloudflare terminates the public TLS with the + # *.riotpiao.com edge certificate, and the connector hop is already + # inside the cluster, so skipping verification on that short hop is the + # least-bad option. Do not widen this to other rules. + # + # SECURITY: this exposes the API to the internet. Authentication is still + # ZITADEL OIDC plus client certificates, but put a Cloudflare Access + # application in front of this hostname as well -- see the note in the + # PR. Without Access, every scanner on the internet reaches the apiserver. + - hostname: k8s.riotpiao.com + service: https://kubernetes.default.svc.cluster.local:443 + originRequest: + noTLSVerify: true - service: http_status:404