3.7 KiB
3.7 KiB
Cloudflare Tunnel Module
This module creates and manages Cloudflare Tunnels using OpenTofu, automating the entire setup process including:
- Creating the Cloudflare tunnel
- Configuring tunnel routing rules
- Setting up DNS records
- 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:
- A Cloudflare account
- API token with the following permissions:
- Account.Cloudflare Tunnel:Edit
- Zone.DNS:Edit
- Zone.Zone:Read
- 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 |