devops/quadlets/modules/hetzner/main.tf

192 lines
3.9 KiB
HCL

terraform {
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.0"
}
}
}
provider "hcloud" {
token = var.hcloud_token
}
variable "hcloud_token" {
description = "Hetzner Cloud API Token"
type = string
sensitive = true
}
variable "ssh_public_key_path" {
description = "Path to SSH public key"
type = string
}
variable "ssh_private_key_path" {
description = "Path to SSH private key"
type = string
}
# variable "acme_email" {
# description = "Email for Let's Encrypt certificates"
# type = string
# default = "engineering@fourlights.nl"
# }
variable "image" {
type = string
default = "ubuntu-24.04"
}
variable "location" {
type = string
default = "nbg1"
}
variable "server_type" {
type = string
default = "cx22"
}
variable "datacenter" {
type = string
default = "nbg1-dc3"
}
variable "name" {
type = string
default = "enterprise"
}
variable "zone" {
type = string
default = "fourlights.dev"
}
variable "hdns_token" {}
variable "ghcr_username" {}
variable "ghcr_token" {}
locals {
acme_email = "engineering+${var.name}@fourlights.nl"
}
resource "hcloud_primary_ip" "server_ipv4" {
name = "${var.name}-ipv4"
type = "ipv4"
assignee_type = "server"
datacenter = var.datacenter
auto_delete = false
}
resource "hcloud_primary_ip" "server_ipv6" {
name = "${var.name}-ipv6"
type = "ipv6"
assignee_type = "server"
datacenter = var.datacenter
auto_delete = false
}
module "dns" {
source = "./dns"
hdns_token = var.hdns_token
zone = var.zone
ipv4_address = hcloud_primary_ip.server_ipv4.ip_address
ipv6_address = hcloud_primary_ip.server_ipv6.ip_address
root = "visualworkplace"
}
# SSH Key
resource "hcloud_ssh_key" "default" {
name = "terraform-key"
public_key = file(var.ssh_public_key_path)
}
# Persistent volume for MinIO
resource "hcloud_volume" "minio_data" {
name = "minio-data"
size = 50
location = var.location
}
# Server with comprehensive cloud-init setup
resource "hcloud_server" "server" {
name = var.name
image = var.image
server_type = var.server_type
location = var.location
ssh_keys = [hcloud_ssh_key.default.id]
user_data = templatefile("${path.module}/cloud-init.yml", {
acme_email = local.acme_email
ssh_public_key = hcloud_ssh_key.default.public_key,
ghcr_username = var.ghcr_username
ghcr_token = var.ghcr_token
})
public_net {
ipv4_enabled = true
ipv6_enabled = true
ipv4 = hcloud_primary_ip.server_ipv4.id
ipv6 = hcloud_primary_ip.server_ipv6.id
}
lifecycle {
replace_triggered_by = [
# This ensures server gets rebuilt when user_data changes
]
}
}
# Attach volume
resource "hcloud_volume_attachment" "minio_data" {
volume_id = hcloud_volume.minio_data.id
server_id = hcloud_server.server.id
automount = false # We'll handle mounting in cloud-init
}
# Wait for cloud-init to complete
resource "null_resource" "wait_for_cloud_init" {
depends_on = [hcloud_server.server]
connection {
type = "ssh"
host = hcloud_server.server.ipv4_address
user = "fourlights"
timeout = "10m"
agent = true
agent_identity = var.ssh_private_key_path
}
provisioner "remote-exec" {
inline = [
"echo 'Waiting for cloud-init to complete...'",
"cloud-init status --wait",
"echo 'Cloud-init completed successfully'"
]
}
}
output "server_ip" {
value = hcloud_server.server.ipv4_address
}
output "haproxy_stats" {
value = "http://${hcloud_server.server.ipv4_address}:8404/stats"
}
output "haproxy_api" {
value = "http://${hcloud_server.server.ipv4_address}:5555"
}
output "server_domain" {
value = module.dns.server_domain
}
output "installed" {
value = true
depends_on = [null_resource.wait_for_cloud_init]
}