feat: add coolify
This commit is contained in:
170
modules/10-services-generic/caddy-proxy/main.tf
Normal file
170
modules/10-services-generic/caddy-proxy/main.tf
Normal file
@@ -0,0 +1,170 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Generate Caddyfile content
|
||||
locals {
|
||||
# Generate the Caddyfile header
|
||||
caddyfile_header = "# Global options\n{\n admin :2019\n}\n\n"
|
||||
|
||||
# Generate site configurations - using separate HTTP and HTTPS blocks but with different hostnames
|
||||
site_blocks = flatten([
|
||||
for site in var.sites : [
|
||||
# HTTPS configuration
|
||||
"# Site configuration for ${site.domain} (HTTPS)",
|
||||
"${site.domain}:${var.https_port} {",
|
||||
" # TLS configuration",
|
||||
" tls internal",
|
||||
"",
|
||||
" # Route configurations",
|
||||
join("\n\n ", [
|
||||
for route in site.routes : <<-ROUTE
|
||||
# Route: ${route.path}
|
||||
handle ${route.path} {
|
||||
reverse_proxy ${route.target_host}:${route.target_port} {
|
||||
${route.websocket ? "# WebSocket protocol handling\n header_up Connection \"Upgrade\"\n header_up Upgrade \"websocket\"" : ""}
|
||||
}
|
||||
}
|
||||
ROUTE
|
||||
]),
|
||||
"}",
|
||||
"",
|
||||
# HTTP configuration with redirect to HTTPS
|
||||
"# HTTP redirect for ${site.domain}",
|
||||
":${var.http_port} {",
|
||||
" redir https://${site.domain}:${var.https_port}{uri} permanent",
|
||||
"}"
|
||||
]
|
||||
])
|
||||
|
||||
# Combine everything into the final Caddyfile
|
||||
caddyfile_content = "${local.caddyfile_header}${join("\n\n", local.site_blocks)}"
|
||||
|
||||
# Define volumes for Caddy
|
||||
volumes = [
|
||||
{
|
||||
host_path = "${var.volume_path}/Caddyfile"
|
||||
container_path = "/etc/caddy/Caddyfile"
|
||||
read_only = false
|
||||
},
|
||||
{
|
||||
host_path = "${var.volume_path}/data"
|
||||
container_path = "/data"
|
||||
read_only = false
|
||||
},
|
||||
{
|
||||
host_path = "${var.volume_path}/config"
|
||||
container_path = "/config"
|
||||
read_only = false
|
||||
}
|
||||
]
|
||||
|
||||
# Create data directories if they don't exist
|
||||
data_directories = [
|
||||
var.volume_path,
|
||||
"${var.volume_path}/data",
|
||||
"${var.volume_path}/config"
|
||||
]
|
||||
|
||||
# Environment variables - convert to the format docker_container resource expects
|
||||
env_vars = var.networks != [] ? ["CADDY_INGRESS_NETWORKS=${join(",", var.networks)}"] : []
|
||||
|
||||
# Health check
|
||||
healthcheck = {
|
||||
test = ["CMD", "wget", "--spider", "--quiet", "http://localhost:80/healthz"]
|
||||
interval = "30s"
|
||||
timeout = "3s"
|
||||
retries = 3
|
||||
}
|
||||
}
|
||||
|
||||
# Create data directories
|
||||
resource "null_resource" "create_directories" {
|
||||
count = length(local.data_directories)
|
||||
|
||||
provisioner "local-exec" {
|
||||
command = "mkdir -p ${local.data_directories[count.index]}"
|
||||
}
|
||||
}
|
||||
|
||||
# Create Caddyfile
|
||||
resource "local_file" "caddyfile" {
|
||||
content = local.caddyfile_content
|
||||
filename = "${var.volume_path}/Caddyfile"
|
||||
depends_on = [null_resource.create_directories]
|
||||
}
|
||||
|
||||
# Pull the image
|
||||
resource "docker_image" "caddy" {
|
||||
name = "${var.image}:${var.tag}"
|
||||
}
|
||||
|
||||
# Create the container
|
||||
resource "docker_container" "caddy" {
|
||||
name = var.container_name
|
||||
image = docker_image.caddy.image_id
|
||||
|
||||
restart = "unless-stopped"
|
||||
|
||||
# Map ports similar to Nginx Proxy Manager
|
||||
ports {
|
||||
internal = 80
|
||||
external = var.http_port
|
||||
protocol = "tcp"
|
||||
}
|
||||
|
||||
ports {
|
||||
internal = 443
|
||||
external = var.https_port
|
||||
protocol = "tcp"
|
||||
}
|
||||
|
||||
# Admin interface port
|
||||
ports {
|
||||
internal = 2019 # Caddy admin API port
|
||||
external = var.admin_port
|
||||
protocol = "tcp"
|
||||
}
|
||||
|
||||
# Set up volumes
|
||||
dynamic "volumes" {
|
||||
for_each = local.volumes
|
||||
content {
|
||||
host_path = volumes.value.host_path
|
||||
container_path = volumes.value.container_path
|
||||
read_only = volumes.value.read_only
|
||||
}
|
||||
}
|
||||
|
||||
# Set environment variables as a list of strings in KEY=VALUE format
|
||||
env = local.env_vars
|
||||
|
||||
# Set networks
|
||||
dynamic "networks_advanced" {
|
||||
for_each = var.networks
|
||||
content {
|
||||
name = networks_advanced.value
|
||||
}
|
||||
}
|
||||
|
||||
# Set health check
|
||||
healthcheck {
|
||||
test = local.healthcheck.test
|
||||
interval = local.healthcheck.interval
|
||||
timeout = local.healthcheck.timeout
|
||||
retries = local.healthcheck.retries
|
||||
}
|
||||
|
||||
# Add watchtower label if monitoring is enabled
|
||||
labels {
|
||||
label = "com.centurylinklabs.watchtower.enable"
|
||||
value = var.monitoring ? "true" : "false"
|
||||
}
|
||||
|
||||
# Make sure Caddyfile is created before starting container
|
||||
depends_on = [local_file.caddyfile]
|
||||
}
|
||||
19
modules/10-services-generic/caddy-proxy/outputs.tf
Normal file
19
modules/10-services-generic/caddy-proxy/outputs.tf
Normal file
@@ -0,0 +1,19 @@
|
||||
output "container_name" {
|
||||
description = "Name of the Caddy proxy container"
|
||||
value = docker_container.caddy.name
|
||||
}
|
||||
|
||||
output "container_ip" {
|
||||
description = "IP address of the Caddy container"
|
||||
value = docker_container.caddy.network_data[0].ip_address
|
||||
}
|
||||
|
||||
output "domains" {
|
||||
description = "Domains being proxied by Caddy"
|
||||
value = [for site in var.sites : site.domain]
|
||||
}
|
||||
|
||||
output "ready" {
|
||||
description = "Boolean indicating if Caddy is ready"
|
||||
value = docker_container.caddy.id != ""
|
||||
}
|
||||
66
modules/10-services-generic/caddy-proxy/variables.tf
Normal file
66
modules/10-services-generic/caddy-proxy/variables.tf
Normal file
@@ -0,0 +1,66 @@
|
||||
variable "container_name" {
|
||||
description = "The name of the Caddy container"
|
||||
type = string
|
||||
default = "caddy-proxy"
|
||||
}
|
||||
|
||||
variable "http_port" {
|
||||
description = "External HTTP port mapping"
|
||||
type = number
|
||||
default = 9080
|
||||
}
|
||||
|
||||
variable "https_port" {
|
||||
description = "External HTTPS port mapping"
|
||||
type = number
|
||||
default = 9443
|
||||
}
|
||||
|
||||
variable "admin_port" {
|
||||
description = "External admin port mapping"
|
||||
type = number
|
||||
default = 9081
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
description = "The image to use for the Caddy container"
|
||||
type = string
|
||||
default = "caddy"
|
||||
}
|
||||
|
||||
variable "tag" {
|
||||
description = "The tag of the Caddy image"
|
||||
type = string
|
||||
default = "latest"
|
||||
}
|
||||
|
||||
variable "volume_path" {
|
||||
description = "Base directory for volumes"
|
||||
type = string
|
||||
default = "/mnt/appdata/caddy"
|
||||
}
|
||||
|
||||
variable "monitoring" {
|
||||
description = "Enable or disable monitoring"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "networks" {
|
||||
description = "List of networks to attach to the Caddy container"
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "sites" {
|
||||
description = "List of sites to proxy"
|
||||
type = list(object({
|
||||
domain = string # Domain name (e.g. deploy.yuris.dev)
|
||||
routes = list(object({
|
||||
path = string # Path to match (e.g. "/app/*" or "/" for root)
|
||||
target_host = string # Target host (e.g. coolify)
|
||||
target_port = number # Target port (e.g. 8080)
|
||||
websocket = bool # Whether this route should be treated as websocket
|
||||
}))
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user