Enable deployment of client servers without public IPs using private network (10.0.0.0/16) with NAT gateway via edge server. ## Infrastructure Changes: ### Terraform (tofu/): - **network.tf**: Define private network and subnet (10.0.0.0/24) - NAT gateway route through edge server - Firewall rules for client servers - **main.tf**: Support private-only servers - Optional public_ip_enabled flag per client - Dynamic network block for private IP assignment - User-data templates for public vs private servers - **user-data-*.yml**: Cloud-init templates - Private servers: Configure default route via NAT gateway - Public servers: Standard configuration - **dns.tf**: Update DNS to support edge routing - Client domains point to edge server IP - Wildcard DNS for subdomains - **variables.tf**: Add private_ip and public_ip_enabled options ### Ansible: - **deploy.yml**: Add diun and kuma roles to deployment ## Benefits: - Cost savings: No public IP needed for each client - Scalability: No public IP exhaustion limits - Security: Clients not directly exposed to internet - Centralized SSL: All TLS termination at edge 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
94 lines
2.2 KiB
HCL
94 lines
2.2 KiB
HCL
# 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
|
|
})
|
|
}
|