# Provider Configuration provider "hcloud" { token = var.hcloud_token } # hcloud provider handles both Cloud and DNS resources # Per-Client SSH Keys resource "hcloud_ssh_key" "client" { for_each = var.clients name = "client-${each.key}-deploy-key" public_key = file("${path.module}/../keys/ssh/${each.key}.pub") } # Firewall Rules resource "hcloud_firewall" "client_firewall" { name = "client-default-firewall" # SSH (restricted - add your management IPs here) rule { direction = "in" protocol = "tcp" port = "22" source_ips = [ "0.0.0.0/0", # CHANGE THIS: Replace with your management IP "::/0" ] } # HTTP (for Let's Encrypt challenge) rule { direction = "in" protocol = "tcp" port = "80" source_ips = [ "0.0.0.0/0", "::/0" ] } # HTTPS rule { direction = "in" protocol = "tcp" port = "443" source_ips = [ "0.0.0.0/0", "::/0" ] } } # Client VPS Instances resource "hcloud_server" "client" { for_each = var.clients name = each.key server_type = each.value.server_type image = "ubuntu-24.04" location = each.value.location ssh_keys = [hcloud_ssh_key.client[each.key].id] firewall_ids = [hcloud_firewall.client_firewall.id] labels = { client = each.key role = "app-server" # Note: labels can't contain special chars, store apps list separately if needed } # Enable backups if requested backups = var.enable_snapshots # Public network configuration (can be disabled for private-only servers) public_net { ipv4_enabled = lookup(each.value, "public_ip_enabled", true) ipv6_enabled = lookup(each.value, "public_ip_enabled", true) } # Private network (required for servers without public IP) dynamic "network" { for_each = lookup(each.value, "private_ip", null) != null ? [1] : [] content { network_id = hcloud_network.private.id ip = each.value.private_ip } } # User data for initial setup user_data = lookup(each.value, "public_ip_enabled", true) == false ? templatefile("${path.module}/user-data-private.yml", { hostname = each.key }) : templatefile("${path.module}/user-data-public.yml", { hostname = each.key }) }