Step 6: Expose only public applications through Cloudflare
This step should take approximately 30 to 40 minutes.
Overview
Cloudflare Tunnel avoids opening an inbound router port. The tunnel connector makes outbound connections to Cloudflare, which forwards only explicitly configured public hostnames. This is different from the internal Traefik entry point created in Step 4.
Practice the skill
-
Create a named remotely managed Cloudflare Tunnel in the dashboard. Create a tunnel token, encrypt it with SOPS, and deploy two
cloudflaredreplicas through Flux. Do not put the token in a plain Helm values file. -
Deploy
traefik-publicwith a distinct ingress class,public, and a ClusterIP Service. Cloudflared reaches this service inside the cluster; it does not need a LAN LoadBalancer address. -
Add one published hostname in Cloudflare, such as
status.example.net, that routes tohttp://traefik-public.traefik-public.svc.cluster.local:80. Cloudflare automatically associates the hostname with the tunnel. Cloudflare's Kubernetes guide describes this connector pattern. -
Deploy the same small test service twice. Its public
Ingressmust name thepublicclass; its internalIngressmust name theinternalclass. Verify the public hostname works over a mobile connection and the internal hostname does not resolve publicly. -
Add Cloudflare Access to administrative public sites such as Grafana. Do not publish the Kubernetes API, Garage administration endpoint, or PostgreSQL.
-
Alert on disconnected tunnel connectors. Cloudflare recommends multiple connector replicas for availability, not autoscaling; existing client connections do not migrate during a connector downscale. Cloudflare Tunnel configuration
What you learned
- Public exposure is an allow-list of hostname-to-service routes.
- A separate ingress class makes accidental exposure less likely.
- Cloudflare Access complements, but does not replace, application authentication.
Continue learning
Continue to Step 7: Deploy shared PostgreSQL and prove it can be restored.
Step 5: Bootstrap GitHub GitOps and encrypted secrets
Connect Flux to a GitHub repository and use SOPS with age so cluster configuration is reviewable without storing plaintext secrets.
Step 7: Deploy shared PostgreSQL and prove it can be restored
Run one private PostgreSQL instance, isolate applications by database role, and validate pgBackRest SFTP recovery.