--- # Flux Kustomization: Cloudflare Tunnel connector — reconciles ./platform/cloudflared. # # ISOLATION IS THE POINT OF THIS FILE. The Deployment it applies CANNOT become Ready until the # operator enrols the tunnel (runbooks/cloudflare-tunnel.md): it ships with REPLACE-ME credentials # and a placeholder UUID, and a wrong or revoked credential later produces the same state. So: # # * ITS OWN Kustomization, not a line in platform/kustomization.yaml. `platform` is wait:true and # gates platform-config, which gates every apps wave; an unenrolled tunnel there would be a # platform-wide stall ON MERGE, with the cause (a missing manual step) invisible from any Flux # condition. Same reasoning, and same failure shape, as vpn-ingress's unfilled server key. # * wait: false. Its pods are legitimately not-Ready whenever the credentials are absent or the # edge is unreachable. Health is reported by the CloudflaredTunnelDown / ReplicasDegraded # alerts (platform/cloudflared/alerts.yaml), not by this Kustomization's Ready condition — # which reaches Ready on APPLY success. # * NOTHING dependsOn THIS, and nothing should. A missing or invalid credentials Secret can then # only ever affect the tunnel itself. conformance/tests/l0-static/cloudflared-ingress-rules # fails the gate if any Kustomization gains `dependsOn: cloudflared`, or if this one stops # being wait:false. # * No Certificate, no HelmRelease, no CRD: nothing in the path for Flux's health checks to wait # on even if wait were flipped (the Certificate-stall lesson). # # dependsOn: [platform-config] — A REAL EDGE. # 1. CRD ORDERING: PodMonitor and PrometheusRule are monitoring.coreos.com CRs whose CRDs are # installed by kube-prometheus-stack in `platform`; platform-config dependsOn platform, so this # edge carries that guarantee transitively (Flux aborts a whole pass on an unknown kind). # 2. THE FAR SIDE OF THE TUNNEL: the Gateway (and so the cilium-gateway-shared Service the ingress # rules point at) is applied by platform-config. A tunnel that comes up before its origin is a # support call. # # ZERO EFFECT ON LIVE TRAFFIC UNTIL DNS MOVES. Cloudflare only sends a hostname through a tunnel # when that hostname's DNS record is a CNAME to .cfargotunnel.com. This change creates no # such record and leaves external-dns, the Gateway annotations, Pi-hole and CoreDNS untouched. apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cloudflared namespace: flux-system spec: interval: 10m retryInterval: 2m timeout: 5m prune: true wait: false dependsOn: - name: platform-config sourceRef: kind: GitRepository name: flux-system path: ./platform/cloudflared # REQUIRED, not boilerplate: platform/cloudflared/config.yaml renders `${BASE_DOMAIN}` into every # ingress hostname, and alerts.yaml into both runbook_url annotations. Without this block the # token becomes the EMPTY STRING and the Kustomization still reports Ready (substitution fails # OPEN), leaving ingress rules for `plex.` and `*.` — a tunnel that 404s everything at best. postBuild: substituteFrom: - kind: ConfigMap name: cluster-vars # SOPS decryption is layered per-environment: clusters/dev and clusters/prod each patch THIS # Kustomization by name with a `decryption:` stanza for cloudflared-credentials.sops.yaml. # Without it the Secret applies cleanly full of ENC[...] and cloudflared cannot authenticate.