# GLAM Heritage Custodian Ontology - Hetzner Infrastructure # Terraform configuration for deploying Oxigraph SPARQL triplestore terraform { required_version = ">= 1.0" required_providers { hcloud = { source = "hetznercloud/hcloud" version = "~> 1.45" } } # Optional: Store state in Terraform Cloud or S3 # backend "s3" { # bucket = "glam-terraform-state" # key = "hetzner/terraform.tfstate" # region = "eu-central-1" # } } # Configure the Hetzner Cloud Provider provider "hcloud" { token = var.hcloud_token } # SSH Key for server access resource "hcloud_ssh_key" "default" { name = "glam-deploy-key" public_key = file(pathexpand(var.ssh_public_key_path)) } # Firewall rules resource "hcloud_firewall" "glam" { name = "glam-firewall" # SSH access rule { direction = "in" protocol = "tcp" port = "22" source_ips = var.ssh_allowed_ips } # HTTP (redirects to HTTPS) 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"] } # SPARQL endpoint (optional direct access, usually via reverse proxy) dynamic "rule" { for_each = length(var.sparql_allowed_ips) > 0 ? [1] : [] content { direction = "in" protocol = "tcp" port = "7878" source_ips = var.sparql_allowed_ips } } # Outbound - allow all rule { direction = "out" protocol = "tcp" port = "1-65535" destination_ips = ["0.0.0.0/0", "::/0"] } rule { direction = "out" protocol = "udp" port = "1-65535" destination_ips = ["0.0.0.0/0", "::/0"] } rule { direction = "out" protocol = "icmp" destination_ips = ["0.0.0.0/0", "::/0"] } } # Persistent storage volume for Oxigraph data resource "hcloud_volume" "data" { name = "glam-data" size = var.volume_size_gb location = var.location format = "ext4" automount = false labels = { project = "glam" purpose = "oxigraph-data" } } # Main server resource "hcloud_server" "glam" { name = "glam-sparql" server_type = var.server_type location = var.location image = "ubuntu-24.04" ssh_keys = [hcloud_ssh_key.default.id] firewall_ids = [hcloud_firewall.glam.id] labels = { project = "glam" environment = var.environment service = "oxigraph" } user_data = templatefile("${path.module}/cloud-init.yaml", { domain = var.domain admin_email = var.admin_email oxigraph_version = var.oxigraph_version volume_device = "/dev/disk/by-id/scsi-0HC_Volume_${hcloud_volume.data.id}" }) # Prevent destroy of server if volume is attached lifecycle { create_before_destroy = true } } # Attach volume to server resource "hcloud_volume_attachment" "data" { volume_id = hcloud_volume.data.id server_id = hcloud_server.glam.id automount = true } # Floating IP for stable endpoint (optional) resource "hcloud_primary_ip" "glam" { count = var.use_floating_ip ? 1 : 0 name = "glam-ip" type = "ipv4" datacenter = "${var.location}-dc14" assignee_type = "server" assignee_id = hcloud_server.glam.id auto_delete = false labels = { project = "glam" } } # Reverse DNS for the server IP resource "hcloud_rdns" "glam" { server_id = hcloud_server.glam.id ip_address = hcloud_server.glam.ipv4_address dns_ptr = var.domain }