locals { db_private_ip = "10.0.1.10" caddy_private_ip = "10.0.1.5" app_base_ip = 20 # App-Nodes: 10.0.1.20, .21, ... database_url = "mysql://${var.db_user}:${var.db_password}@${local.db_private_ip}:3306/${var.db_name}?serverVersion=11.4.0-MariaDB&charset=utf8mb4" # Caddy-Upstreams = private IPs der App-Nodes (:80) app_upstreams = join(" ", [for i in range(var.app_count) : "10.0.1.${local.app_base_ip + i}:80"]) ask_upstream = "10.0.1.${local.app_base_ip}" # app-1 für die On-Demand-TLS-Abfrage } resource "hcloud_ssh_key" "admin" { name = "vcard4-admin" public_key = var.ssh_public_key } # --- Privates Netz --- resource "hcloud_network" "net" { name = "vcard4-net" ip_range = "10.0.0.0/16" } resource "hcloud_network_subnet" "subnet" { network_id = hcloud_network.net.id type = "cloud" network_zone = var.network_zone ip_range = "10.0.1.0/24" } # --- Firewalls --- resource "hcloud_firewall" "app" { name = "vcard4-app-fw" rule { direction = "in" protocol = "tcp" port = "22" source_ips = [var.admin_cidr] } rule { direction = "in" protocol = "tcp" port = "80" source_ips = ["10.0.0.0/16"] # nur aus dem privaten Netz (Load Balancer) } } resource "hcloud_firewall" "db" { name = "vcard4-db-fw" rule { direction = "in" protocol = "tcp" port = "22" source_ips = [var.admin_cidr] } rule { direction = "in" protocol = "tcp" port = "3306" source_ips = ["10.0.0.0/16"] # nur App-Nodes } } # --- DB-Node --- resource "hcloud_server" "db" { name = "vcard4-db" server_type = var.db_server_type image = "ubuntu-24.04" location = var.location ssh_keys = [hcloud_ssh_key.admin.id] firewall_ids = [hcloud_firewall.db.id] user_data = templatefile("${path.module}/cloud-init-db.yaml.tftpl", { db_name = var.db_name db_user = var.db_user db_password = var.db_password db_root_password = var.db_root_password }) network { network_id = hcloud_network.net.id ip = local.db_private_ip } depends_on = [hcloud_network_subnet.subnet] } # --- App-Nodes (zustandslos) --- resource "hcloud_server" "app" { count = var.app_count name = "vcard4-app-${count.index + 1}" server_type = var.app_server_type image = "ubuntu-24.04" location = var.location ssh_keys = [hcloud_ssh_key.admin.id] firewall_ids = [hcloud_firewall.app.id] user_data = templatefile("${path.module}/cloud-init-app.yaml.tftpl", { repo_url = var.repo_url repo_branch = var.repo_branch run_migrations = count.index == 0 # Migrationen nur auf dem ersten Node app_secret = var.app_secret database_url = local.database_url domain = var.domain cors_allow_origin = "^https?://(www\\.)?${replace(var.domain, ".", "\\.")}$" jwt_passphrase = var.jwt_passphrase jwt_private_key = var.jwt_private_key jwt_public_key = var.jwt_public_key s3_endpoint = var.s3_endpoint s3_region = var.s3_region s3_bucket = var.s3_bucket s3_key = var.s3_key s3_secret = var.s3_secret }) network { network_id = hcloud_network.net.id ip = "10.0.1.${local.app_base_ip + count.index}" } # cloud-init zählt nur beim Erstboot; Code-Updates laufen über den Rollout # (terraform_data.app_deploy) → Server nicht wegen user_data-Änderung ersetzen. lifecycle { ignore_changes = [user_data] } depends_on = [hcloud_network_subnet.subnet, hcloud_server.db] } # --- Caddy-Edge (TLS-Terminierung + Reverse-Proxy/Load-Balancing) --- resource "hcloud_firewall" "caddy" { name = "vcard4-caddy-fw" rule { direction = "in" protocol = "tcp" port = "22" source_ips = [var.admin_cidr] } rule { direction = "in" protocol = "tcp" port = "80" source_ips = ["0.0.0.0/0", "::/0"] } rule { direction = "in" protocol = "tcp" port = "443" source_ips = ["0.0.0.0/0", "::/0"] } rule { direction = "in" protocol = "udp" port = "443" source_ips = ["0.0.0.0/0", "::/0"] } } resource "hcloud_server" "caddy" { name = "vcard4-caddy" server_type = var.app_server_type image = "ubuntu-24.04" location = var.location ssh_keys = [hcloud_ssh_key.admin.id] firewall_ids = [hcloud_firewall.caddy.id] user_data = templatefile("${path.module}/cloud-init-caddy.yaml.tftpl", { acme_email = var.acme_email domain = var.domain app_upstreams = local.app_upstreams ask_upstream = local.ask_upstream }) network { network_id = hcloud_network.net.id ip = local.caddy_private_ip } depends_on = [hcloud_network_subnet.subnet, hcloud_server.app] }