Skip to main content

Cloudflare tunnel

Expose services on a domain you own through Cloudflare's edge network. The cluster runs a cloudflared Deployment that holds an outbound-only connection to Cloudflare — no inbound ports, no public IP, no manual TLS certificates.

The novice path — from a fresh provision-host container to a service reachable on the public internet — is three commands plus a one-time dashboard click.

Prerequisites

LocalCloudflare
The UIS provision-host container running (./uis start)An account with a domain you own (DNS managed by Cloudflare)
A cluster active (uis platform list shows one as ✓ running (active)) — rancher-desktop worksA tunnel created in the Zero Trust dashboard (you need its token)

This guide assumes rancher-desktop as the target cluster — that's what was verified for this round. The pipeline is cluster-agnostic, so the same commands work against AKS once the platform is up.

Quick start — three commands

./uis network init cloudflare     # 1. interactive wizard, paste the tunnel token
./uis network up cloudflare # 2. push token to cluster, deploy cloudflared
./uis network verify cloudflare # 3. confirm DNS + port 7844 + e2e probe

The sections below walk through what each command does and what output to expect.

1. Create the tunnel in the Cloudflare dashboard

Before running any UIS command, create the tunnel in Cloudflare. UIS doesn't talk to the Cloudflare API — it deploys the in-cluster connector that points at a tunnel you created in the dashboard.

  1. Go to Zero Trust dashboard → Networks → Tunnels.
  2. Create a tunnel → Cloudflared connector type → pick a name.
  3. Skip the install instructions for Linux/macOS/Windows — UIS deploys the connector for you. Copy the tunnel token (the long string starting with ey...) from the install command shown on the page.
  4. Add a Public Hostname routing rule:
    • Subdomain: * (or a specific name like whoami)
    • Domain: pick your domain (e.g. skryter.no)
    • Service: HTTP → traefik.kube-system.svc.cluster.local:80

Routing happens server-side at Cloudflare; the cluster only needs to know the token.

2. Run the init wizard

./uis network init cloudflare

The wizard prompts for the tunnel token (required) and the base domain (optional — needed only for the end-to-end probe in verify). It writes two files:

FileUsed by
.uis.secrets/service-keys/cloudflare.envuis network status cloudflare — for the "configured / running" detection
.uis.secrets/secrets-config/00-common-values.env.template (patched)uis secrets generate — feeds the token into the cluster's urbalurba-secrets k8s Secret

If the file already exists, the wizard offers three options: skip (keep existing), re-prompt (overwrite), or show (print path + values and exit).

3. Deploy the cloudflared pods

./uis network up cloudflare

Two stages:

  1. uis secrets generate + uis secrets apply — pushes the token from the local env file into the urbalurba-secrets Secret in the cluster. This is the same pipeline every other UIS secret uses.
  2. ansible-playbook 820-deploy-network-cloudflare-tunnel.yml — applies the static 820-cloudflare-tunnel-base.yaml manifest (a Deployment with one cloudflared replica) and waits for the pod to reach Running. The playbook also runs a final HTTPS probe through your domain if BASE_DOMAIN_CLOUDFLARE is set.

The pod registers with Cloudflare's edge within ~15 seconds. After that, any service with a Traefik IngressRoute matching *.your-domain.com is reachable on the public internet.

4. Verify

./uis network verify cloudflare

Runs five checks:

#CheckWhat it confirms
1SecretsCLOUDFLARE_TUNNEL_TOKEN is set in the cluster Secret and not a placeholder
2NetworkDNS resolves region1.v2.argotunnel.com and TCP/7844 is reachable (corporate firewalls sometimes block it)
3PodsAll cloudflared pods are in Running phase
4LogsRecent pod logs contain Registered tunnel connection
5End-to-endHTTPS probe to https://<BASE_DOMAIN_CLOUDFLARE> returns 200/301/302/404 (skipped if the domain wasn't set in init)

A PASS on every line means traffic is flowing through the tunnel.

5. Day-2 commands

./uis network status cloudflare   # config + pod state, plus log tail if pods aren't Running
./uis network list # one-line state across all providers
./uis network down cloudflare # remove the in-cluster Deployment

uis network down cloudflare only deletes the in-cluster cloudflared Deployment. The tunnel itself in the Cloudflare dashboard is preserved, so re-running uis network up cloudflare reconnects the same tunnel. To retire the tunnel completely, delete it from Zero Trust → Networks → Tunnels.

The .uis.secrets/service-keys/cloudflare.env file is preserved across down / up cycles so you don't have to re-paste the token. Delete it manually if you want a full reset.

How traffic flows

Once the tunnel is up:

internet user

Cloudflare edge (terminates TLS, optionally adds WAF / DDoS rules)

cloudflared pod (outbound-only)

Traefik IngressRoute (HostRegexp match)

your service pod

The IngressRoutes don't need to know they're being reached through Cloudflare — they match by hostname (HostRegexp patterns), so the same route serves whoami.localhost, whoami.your-device.ts.net and whoami.your-domain.com.

Troubleshooting

uis network up cloudflare fails at the playbook step with "placeholder value"

The token from the dashboard wasn't picked up by the secrets pipeline. Verify both files have the real token (not your-cloudflare-tunnel-token-here):

./uis network status cloudflare     # confirms the local env file
./uis secrets status # confirms the master template

If the master template still has the placeholder, re-run ./uis network init cloudflare. The wizard patches both files atomically.

Pods come up but the domain returns 502

The cloudflared pods are connected to Cloudflare's edge but the routing rule in the dashboard points at a service that isn't ready. Check the Traefik route:

kubectl get ingressroute -A
kubectl -n kube-system get svc traefik

The dashboard rule should send traffic to traefik.kube-system.svc.cluster.local:80 (or :443 if you're terminating TLS in the cluster).

./uis network verify cloudflare says port 7844 is blocked

Corporate firewalls sometimes block outbound 7844. The tunnel won't establish. Try from a different network, or contact your network team — Cloudflare publishes the outbound port list.

Cost

The cloudflared connector is free. Cloudflare's free plan covers tunnels, WAF basics, and unmetered DDoS protection. You pay for the domain registration ($10–15/year for most TLDs) and only need a paid Cloudflare plan if you want advanced WAF rules, image optimization, or higher request limits.

Learn more