Files
homelab-opentofu/modules/01-networking/cloudflared-tunnel/README.md
Yuris Cakranegara cac26957a8 first commit
2025-06-06 12:01:54 +10:00

3.7 KiB

Cloudflare Tunnel Module

This module creates and manages Cloudflare Tunnels using OpenTofu, automating the entire setup process including:

  1. Creating the Cloudflare tunnel
  2. Configuring tunnel routing rules
  3. Setting up DNS records
  4. Deploying the cloudflared tunnel container

Features

  • Automated Tunnel Management: Creates and configures Cloudflare tunnels via the API
  • Multiple Service Support: Route multiple applications through a single tunnel
  • DNS Management: Automatically creates DNS records for your applications
  • Docker Integration: Deploys the cloudflared container with proper configuration
  • Secret Management: Auto-generates tunnel secrets if not provided

Prerequisites

Before using this module, you need:

  1. A Cloudflare account
  2. API token with the following permissions:
    • Account.Cloudflare Tunnel:Edit
    • Zone.DNS:Edit
    • Zone.Zone:Read
  3. Your Cloudflare account ID and zone ID

Usage

module "homelab_tunnel" {
  source = "./modules/01-networking/cloudflared-tunnel"
  
  cloudflare_account_id = var.cloudflare_account_id
  cloudflare_zone_id    = var.cloudflare_zone_id
  
  tunnel_name    = "homelab-tunnel"
  container_name = "cloudflared-homelab"
  
  ingress_rules = [
    {
      hostname = "budget.example.com"
      service  = "http://actualbudget:5006"
    },
    {
      hostname = "dashboard.example.com"
      service  = "http://homepage:3000"
    }
  ]
}

Connecting with the Cloudflare Globals Module

For cleaner code organization, use the globals module:

module "cloudflare_globals" {
  source = "./modules/00-globals/cloudflare"
  
  cloudflare_api_token = var.cloudflare_api_token
  cloudflare_account_id = var.cloudflare_account_id
  cloudflare_zone_id = var.cloudflare_zone_id
  domain = "example.com"
}

module "homelab_tunnel" {
  source = "./modules/01-networking/cloudflared-tunnel"
  
  cloudflare_account_id = module.cloudflare_globals.cloudflare_account_id
  cloudflare_zone_id    = module.cloudflare_globals.cloudflare_zone_id
  
  tunnel_name = "homelab-tunnel"
  
  ingress_rules = [
    {
      hostname = "budget.${module.cloudflare_globals.domain}"
      service  = "http://actualbudget:5006"
    }
  ]
}

Variables

Name Description Type Default
cloudflare_account_id Cloudflare account ID string (required)
cloudflare_zone_id Cloudflare zone ID for your domain string (required)
container_name Name of the Cloudflare tunnel container string "" (defaults to "cloudflared-{tunnel_name}")
image_tag Docker image tag for cloudflared string "latest"
tunnel_name Name of the tunnel string (required)
tunnel_secret Secret for the tunnel string "" (auto-generated if empty)
ingress_rules List of ingress rules list(object) (required)
monitoring Enable monitoring via Watchtower bool true

Ingress Rules Object Structure

ingress_rules = [
  {
    hostname = "app.example.com"         # FQDN for the service
    service = "http://container:port"    # Internal service URL
    path = "/api/*"                      # Optional path pattern
    create_dns_record = true             # Whether to create DNS record (default: true)
  }
]

Outputs

Name Description
tunnel_id ID of the created tunnel
tunnel_name Name of the tunnel
tunnel_token Token for the tunnel (sensitive)
cname_target CNAME target for the tunnel
dns_records Map of created DNS records
container_name Name of the cloudflared container
container_id ID of the cloudflared container
image_id ID of the cloudflared image
ip_address IP address of the cloudflared container