# Caddy Proxy Module This module creates a Caddy reverse proxy server that dynamically configures itself based on service definitions passed to it. ## Overview The Caddy Proxy module: - Accepts service definitions that specify whether to expose them via reverse proxy - Dynamically generates Caddyfile configuration from these service definitions - Supports custom Caddy configuration blocks per service - Deploys a Caddy container with the generated configuration - Manages TLS certificates automatically using Let's Encrypt - Creates DNS records for services with configurable Cloudflare proxying settings ## Usage ### Basic Integration Add the module to your main Terraform configuration: ```hcl module "homelab_caddy_proxy" { source = "./modules/01-networking/caddy-proxy" domain = "yourdomain.com" tls_email = "your-email@example.com" # For Let's Encrypt container_name = "caddy-proxy" cloudflare_zone_id = module.cloudflare_globals.cloudflare_zone_id external_ip = module.cloudflare_globals.external_ip service_definitions = module.services.service_definitions networks = ["your-docker-network"] monitoring = true } ``` ### Service Definition Format Services should include the following fields to be properly exposed through Caddy: ```hcl { name = "service-name" endpoint = "service-container:port" subdomains = ["app", "dashboard"] # Will create app.yourdomain.com, dashboard.yourdomain.com # Specify how to publish this service: "tunnel", "reverse_proxy", or "both" (default) publish_via = "both" # Control whether the DNS record is proxied through Cloudflare (default: true) proxied = true # Option 1: Simplified Caddy configuration via options caddy_options = { "health_path" = "/health" "health_interval" = "30s" "header_up X-Real-IP" = "{http.request.remote}" # Additional reverse_proxy options as needed } # Option 2: Full custom Caddy configuration (takes precedence if both are provided) caddy_config = <<-EOT # Raw Caddy configuration goes here reverse_proxy /api/* api-backend:8080 reverse_proxy /* frontend:3000 header X-Powered-By "My Awesome Homelab" log { output file /var/log/access.log } EOT } ``` The `publish_via` field controls which networking module(s) will expose the service: - `"tunnel"`: Service will only be published via Cloudflare tunnel - `"reverse_proxy"`: Service will only be exposed via Caddy reverse proxy - `"both"`: Service will be published via both methods (default) ## Variables | Variable | Description | Type | Default | |----------|-------------|------|---------| | `container_name` | The name of the Caddy container | `string` | `""` (generates "caddy-proxy") | | `image_tag` | The tag of the Caddy Docker image to use | `string` | `"latest"` | | `domain` | The domain name to use for services | `string` | - | | `tls_email` | Email address for Let's Encrypt | `string` | - | | `service_definitions` | List of service definitions to evaluate | `list(object)` | - | | `networks` | List of Docker networks to connect to | `list(string)` | `[]` | | `monitoring` | Whether to enable monitoring for the container | `bool` | `false` | | `cloudflare_zone_id` | Cloudflare Zone ID for creating DNS records | `string` | `""` | | `external_ip` | External IP address for A records | `string` | `""` | ## Outputs | Output | Description | |--------|-------------| | `container_name` | The name of the deployed Caddy container | | `config_hash` | The SHA256 hash of the generated Caddyfile content | | `service_sites` | Map of generated Caddy site configurations | ## Example Service Integration ### Basic Service with Default Settings ```hcl # Example based on jellyfin (reverse-proxy only with direct IP exposure) output "service_definition" { description = "Service definition for a media server" value = { name = "jellyfin" primary_port = 8096 endpoint = "http://jellyfin:8096" subdomains = ["media"] publish_via = "reverse_proxy" # Only expose via Caddy reverse proxy proxied = false # Don't proxy through Cloudflare (expose direct IP) } } ``` ### Service with Custom Caddy Configuration ```hcl # Example showing a service with custom Caddy configuration output "service_definition" { description = "Service definition with custom Caddy configuration" value = { name = "custom-service" primary_port = 8080 endpoint = "http://custom-service:8080" subdomains = ["custom"] publish_via = "reverse_proxy" proxied = true # Use Cloudflare proxying (default) caddy_config = <<-EOT # Handle API requests specially handle /api/* { reverse_proxy custom-service:8080 { header_up X-Real-IP {remote} } } # Handle all other requests handle { reverse_proxy custom-service:8080 header +Access-Control-Allow-Origin "*" } EOT } } ```