terraform { required_version = ">= 1.6" required_providers { google = { source = "hashicorp/google" version = "~> 5.0" } } # Store state in GCS — create the bucket manually once before first apply backend "gcs" { bucket = "drb-tf-state" prefix = "drb/state" } } provider "google" { project = var.project_id region = var.region } # --------------------------------------------------------------------------- # Static external IP # --------------------------------------------------------------------------- resource "google_compute_address" "drb" { name = "drb-server-ip" region = var.region } # --------------------------------------------------------------------------- # Firewall rules # --------------------------------------------------------------------------- resource "google_compute_firewall" "allow_web" { name = "drb-allow-web" network = "default" allow { protocol = "tcp" ports = ["80", "443"] } source_ranges = ["0.0.0.0/0"] target_tags = ["drb-server"] } resource "google_compute_firewall" "allow_ssh" { name = "drb-allow-ssh" network = "default" allow { protocol = "tcp" ports = ["22"] } # Restrict SSH to your IP(s) and Gitea runner IP source_ranges = var.allowed_ssh_cidrs target_tags = ["drb-server"] } # MQTT is NOT exposed externally — edge nodes connect via WireGuard (see below) # If you need to temporarily allow direct MQTT access for testing, uncomment and # restrict source_ranges to your node IPs. # # resource "google_compute_firewall" "allow_mqtt" { # name = "drb-allow-mqtt" # network = "default" # allow { # protocol = "tcp" # ports = ["8883"] # TLS MQTT, not 1883 # } # source_ranges = ["YOUR_NODE_CIDR"] # target_tags = ["drb-server"] # } # --------------------------------------------------------------------------- # Compute Engine VM # --------------------------------------------------------------------------- resource "google_compute_instance" "drb_server" { name = "drb-server" machine_type = var.machine_type zone = var.zone tags = ["drb-server"] boot_disk { initialize_params { image = "debian-cloud/debian-12" size = 30 # GB — enough for Docker images + mosquitto data type = "pd-balanced" } } network_interface { network = "default" access_config { nat_ip = google_compute_address.drb.address } } metadata = { ssh-keys = "${var.ssh_user}:${var.ssh_public_key}" } # Startup script runs once on first boot to install Docker + Caddy metadata_startup_script = file("${path.module}/startup.sh") # Allow the VM to pull from Artifact Registry using its service account service_account { scopes = ["cloud-platform"] } lifecycle { # Prevent Terraform from destroying + recreating on metadata changes ignore_changes = [metadata_startup_script] } } # --------------------------------------------------------------------------- # Cloud DNS records # --------------------------------------------------------------------------- resource "google_dns_record_set" "app" { name = "app.${var.domain}." type = "A" ttl = 300 managed_zone = var.dns_zone_name rrdatas = [google_compute_address.drb.address] } resource "google_dns_record_set" "api" { name = "api.${var.domain}." type = "A" ttl = 300 managed_zone = var.dns_zone_name rrdatas = [google_compute_address.drb.address] }