The apiserver now authenticates against ZITADEL (PR #87, applied and verified), so kubectl can work from outside the LAN without a client certificate. This publishes it through the existing Cloudflare Tunnel.
Two deliberate details
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.
originRequest.noTLSVerify: true 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. Scoped to this one rule.
Port
Cloudflare Tunnel hostname rules serve on 443 and do not proxy arbitrary ports. kubeconfig must use https://k8s.riotpiao.com with no :6443.
Already done out-of-band
DNS CNAME k8s.riotpiao.com → 32d0bf93-….cfargotunnel.com, proxied (created via the Cloudflare API, verified resolving).
The hostname is not yet reachable because this ConfigMap change is uncommitted and ArgoCD self-heal reverted the direct apply.
Security — please read
This exposes the Kubernetes API to the internet. Authentication remains ZITADEL OIDC plus client certificates, so an unauthenticated caller gets 401. The residual risk is scanner noise and DoS, not auth bypass.
Recommended follow-up: a Cloudflare Access application in front of k8s.riotpiao.com. Trade-off worth knowing before you choose:
Access with a service token is the secure option, but kubectl cannot send arbitrary headers, so it needs either a local cloudflared access proxy or a kubeconfig proxy-url.
Access with browser SSO does not fit a CLI client well.
So there is a real convenience/security trade. My read: enable Access if this hostname will be internet-facing long-term; otherwise keep the OIDC requirement alone and accept the scanner traffic.
## Why
The apiserver now authenticates against ZITADEL (PR #87, applied and verified), so `kubectl` can work from outside the LAN without a client certificate. This publishes it through the existing Cloudflare Tunnel.
## Two deliberate details
1. **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: true` 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. Scoped to this one rule.
## Port
Cloudflare Tunnel hostname rules serve on **443** and do not proxy arbitrary ports. kubeconfig must use `https://k8s.riotpiao.com` with **no `:6443`**.
## Already done out-of-band
- DNS CNAME `k8s.riotpiao.com` → `32d0bf93-….cfargotunnel.com`, proxied (created via the Cloudflare API, verified resolving).
- The hostname is not yet reachable because this ConfigMap change is uncommitted and ArgoCD self-heal reverted the direct apply.
## Security — please read
This exposes the Kubernetes API to the internet. Authentication remains ZITADEL OIDC plus client certificates, so an unauthenticated caller gets 401. The residual risk is scanner noise and DoS, not auth bypass.
**Recommended follow-up: a Cloudflare Access application in front of `k8s.riotpiao.com`.** Trade-off worth knowing before you choose:
- Access with a **service token** is the secure option, but `kubectl` cannot send arbitrary headers, so it needs either a local `cloudflared access` proxy or a kubeconfig `proxy-url`.
- Access with **browser SSO** does not fit a CLI client well.
So there is a real convenience/security trade. My read: enable Access if this hostname will be internet-facing long-term; otherwise keep the OIDC requirement alone and accept the scanner traffic.
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.
rock
merged commit cf3223499e into main2026-11-03 21:48:07 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Why
The apiserver now authenticates against ZITADEL (PR #87, applied and verified), so
kubectlcan work from outside the LAN without a client certificate. This publishes it through the existing Cloudflare Tunnel.Two deliberate details
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.originRequest.noTLSVerify: trueis 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.comedge certificate and the connector hop is already inside the cluster. Scoped to this one rule.Port
Cloudflare Tunnel hostname rules serve on 443 and do not proxy arbitrary ports. kubeconfig must use
https://k8s.riotpiao.comwith no:6443.Already done out-of-band
k8s.riotpiao.com→32d0bf93-….cfargotunnel.com, proxied (created via the Cloudflare API, verified resolving).Security — please read
This exposes the Kubernetes API to the internet. Authentication remains ZITADEL OIDC plus client certificates, so an unauthenticated caller gets 401. The residual risk is scanner noise and DoS, not auth bypass.
Recommended follow-up: a Cloudflare Access application in front of
k8s.riotpiao.com. Trade-off worth knowing before you choose:kubectlcannot send arbitrary headers, so it needs either a localcloudflared accessproxy or a kubeconfigproxy-url.So there is a real convenience/security trade. My read: enable Access if this hostname will be internet-facing long-term; otherwise keep the OIDC requirement alone and accept the scanner traffic.