Post

Cloudflare

Cloudflare

Cloudflare Tunnel

Outbound-only Cloudflare Tunnel connecting the homelab to the public internet without opening any inbound firewall ports. Runs as cloudflared-deployment in the default namespace of the k3s cluster.

Stack

ItemValue
Imagecloudflare/cloudflared:2026.10.0
Namespacedefault
Replicas1, pinned to node cm4-left (nodeSelector)
Resourcesrequests 20m/32Mi, limits 200m/128Mi
Reloaderreloader.stakater.com/auto: "true" — auto-restarts if the tunnel token Secret changes

How it works

cloudflared makes an outbound QUIC/HTTP2 connection to Cloudflare’s edge network and authenticates with a tunnel token (TUNNEL_TOKEN, from Secret/tunnel-token, key token). There is no Service, Ingress, or PersistentVolumeClaim for this workload — it’s stateless and only ever originates connections, never accepts them directly.

Public hostname routing rules (which hostname maps to which internal target) are configured entirely in the Cloudflare Zero Trust dashboard, not in this repo. Matched requests are forwarded over the tunnel to internal targets — primarily Traefik’s websecure (:443) Service, which then routes by hostname to whichever app is being requested.

1
Client → Cloudflare Edge → Tunnel (outbound from pod) → cloudflared pod → Traefik :443 → target Service

Container detail

1
2
3
4
5
6
7
8
9
command:
  - cloudflared
  - tunnel
  - --no-autoupdate
  - --loglevel
  - info
  - --metrics
  - 0.0.0.0:2000
  - run
  • securityContext.sysctls: net.ipv4.ping_group_range=65532 65532 — allows the container to send ICMP (ping/traceroute) to internal backends, since cloudflared doesn’t have NET_ADMIN by default.
  • livenessProbe: GET /ready :2000, failureThreshold: 1, initialDelaySeconds: 10, periodSeconds: 10 — cloudflared’s /ready endpoint only returns 200 once it has an active connection to Cloudflare’s edge, so a failed probe means the tunnel itself is down, not just the process.

Security note

The tunnel token is stored as plaintext stringData in tunnel-token.yaml in the source repo, same pattern as other secrets in this workspace — treat that repo’s contents as sensitive, not just the live cluster Secret.

Deploy

1
kubectl apply -f deployment.yaml -f tunnel-token.yaml
This post is licensed under CC BY 4.0 by the author.