Files
home-network-k3s-impl/platform/cloudflared
jakman85andClaude Opus 5.5 b85d1e3ed7 feat(vuln): vuln-scanner platform manifests, Flux tier, alerts, L0/L2/L3 tests
Hand-authored platform/vuln-scanner (non-gating Flux tier, digest-pinned Trivy 0.76.1 and
python 3.14.9-alpine, read-only RBAC, per-pod oauth2-proxy, internal-only cve.<domain>),
five alerts with promtool tests, R-VULN-01..09 registry entries, and vuln-* L0 checks with
mutation self-tests. src/ and the bot workflow are integrated separately.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 09:42:52 -06:00
..

platform/cloudflared

Cloudflare Tunnel connector: inbound HTTPS from the Cloudflare edge to the shared Gateway, outbound-only from the cluster (no router port forward, no hairpin, no split-DNS dependency).

  • Flux tier: clusters/base/cloudflared.yaml — its own Kustomization, dependsOn: [platform-config], wait: false, and nothing depends on it. A missing or invalid credential can affect only the tunnel.
  • Runbook (enrolment, canary, alerts, rollback): runbooks/cloudflare-tunnel.md
  • Design record: decisions/2026-11-08-cloudflare-tunnel.md
  • Guard: conformance/tests/l0-static/cloudflared-ingress-rules
File What it is
config.yaml The locally-managed tunnel: literal tunnel UUID + ingress rules. LAN/VPN-only hosts → 404, apex + wildcard → https://cilium-gateway-shared.gateway.svc.cluster.local:443 with matchSNItoHost, catch-all 404. Never the Kubernetes API.
cloudflared-credentials.sops.yaml SOPS-encrypted tunnel credentials JSON. Ships with REPLACE-ME; the operator fills it.
deployment.yaml 2 replicas, hard spread across nodes, non-root, read-only root fs, pinned digest; PDB minAvailable: 1.
networkpolicy.yaml default-deny (single owner — not an app namespace) + Prometheus scrape allow + egress CNP: world 7844 tcp/udp and 443, the Gateway (ingress entity), and Gateway backends by gateway-access=shared minus the LAN-only namespaces.
servicemonitor.yaml, alerts.yaml Headless metrics Service + ServiceMonitor scraping :2000, and the two alerts, both written to fire (not go quiet) when their series vanish.

Cloudflare sends a hostname through the tunnel only when its DNS record is a proxied CNAME to <UUID>.cfargotunnel.com; nothing in this directory creates one. Those records are published by external-dns from the shared Gateway's target annotation (Phase 2, PR #156; see platform/externaldns/README.md). LAN resolution: catalog/pihole.yaml (explicit names only since 2026-11-09), so public names reach Cloudflare from the LAN too.