Skip to content

Cloudflare Tunnel Module

Terraform module for deploying a remotely-managed Cloudflare Tunnel connector (cloudflared) to Kubernetes. Exposes in-cluster services through Cloudflare's edge without inbound ports, bypassing ISP CGNAT.

Architecture

This module runs only the connector. The tunnel definition, its public hostnames, DNS records, and Cloudflare Access policies are managed in the Cloudflare dashboard, not Terraform. The remotely-managed connector model keeps that config server-side and delivers it to the connector via the tunnel token, so Terraform needs only the token and never holds the routing config.

flowchart LR
  Internet["Internet"]:::aux -->|"HTTPS 443"| Edge["Cloudflare Edge"]:::aux
  Edge -->|"outbound tunnel<br/>TCP 7844"| Conn["cloudflared<br/>connector pods"]
  Conn -->|"catch-all hostname<br/>HTTPS, No TLS Verify"| Ingress["nginx-ingress-nginx-controller.nginx.svc:443"]
  Ingress -->|"route by Host"| Apps["cluster services"]

  classDef aux stroke:#78909c,stroke-dasharray:2 2

The single catch-all public hostname points at the ingress-nginx controller Service, and ingress-nginx routes by Host as usual.

Requirements

  • The cluster must reach Cloudflare outbound on TCP 7844 (tunnel) and 443.
  • The NGINX module must be deployed first (depends_on = [module.nginx]).
  • A tunnel token from the Cloudflare dashboard (see below).

Configuration

Variable Description Default
cloudflare_tunnel_token Tunnel token (sensitive). Cloudflare issues it per tunnel. (required when enabled)
cloudflare_tunnel_chart_version cloudflare-tunnel-remote Helm chart version (pinned). 0.1.2
cloudflare_tunnel_image_tag cloudflared image tag. Empty uses the chart default. ""
cloudflare_tunnel_replica_count Number of replicas. HA only; do not autoscale (downscaling drops live connections). 2

Enable the module with cloudflare_tunnel_enable = true (top-level variable, default false).

Getting the tunnel token

Dashboard > Zero Trust > Networks > Tunnels > Create a tunnel > cloudflared > name it > Save. On the install screen, copy the value after --token (the long eyJ... string). Set it via TF_VAR_cloudflare_tunnel_token.

The token is marked sensitive and passed via Helm set_sensitive, so it stays out of plan/apply output. It is still written to Terraform state in cleartext. Keep state on an encrypted, access-controlled backend.

Chart

Property Value
Repository https://cloudflare.github.io/helm-charts
Chart cloudflare-tunnel-remote
Version 0.1.2

References