33700448bf
Provisions e2-micro VM (us-east1-b, free tier) with static IP, SSH and web firewall rules, Docker + Caddy startup script, and IAM bindings for Firestore and GCS access via ADC. Imports existing drb-calls bucket and c2-server Firestore database into state. Ansible roles handle first-time setup (swap, docker group) and all subsequent deploys via rsync + docker compose, with secrets managed via Ansible Vault. DNS stays on AWS Route 53.
190 lines
5.5 KiB
Terraform
190 lines
5.5 KiB
Terraform
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
|
|
# Uncomment once GCS bucket permissions are confirmed working.
|
|
# backend "gcs" {
|
|
# bucket = "drb-tf-state"
|
|
# prefix = "drb/state"
|
|
# }
|
|
}
|
|
|
|
provider "google" {
|
|
project = var.project_id
|
|
region = var.region
|
|
}
|
|
|
|
# Pull live project metadata (number, name) without hardcoding them.
|
|
data "google_project" "current" {}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 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 — free tier covers 30GB pd-standard on e2-micro
|
|
type = "pd-standard"
|
|
}
|
|
}
|
|
|
|
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")
|
|
|
|
# The default compute service account with cloud-platform scope gives the VM
|
|
# full access to GCS and Firestore in the same project — no key file needed.
|
|
service_account {
|
|
scopes = ["cloud-platform"]
|
|
}
|
|
|
|
lifecycle {
|
|
# Prevent Terraform from destroying + recreating on metadata changes
|
|
ignore_changes = [metadata_startup_script]
|
|
}
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# IAM — grant the VM's default compute SA access to Firestore and GCS.
|
|
# Since Firebase/GCS already live in the same project, no key file is needed —
|
|
# the VM authenticates via the metadata server (ADC).
|
|
# ---------------------------------------------------------------------------
|
|
|
|
locals {
|
|
compute_sa = "serviceAccount:${data.google_project.current.number}-compute@developer.gserviceaccount.com"
|
|
}
|
|
|
|
resource "google_project_iam_member" "drb_firestore" {
|
|
project = var.project_id
|
|
role = "roles/datastore.user"
|
|
member = local.compute_sa
|
|
}
|
|
|
|
resource "google_project_iam_member" "drb_gcs" {
|
|
project = var.project_id
|
|
role = "roles/storage.objectAdmin"
|
|
member = local.compute_sa
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Firestore database — import existing, manages schema/settings going forward
|
|
# ---------------------------------------------------------------------------
|
|
|
|
import {
|
|
id = "projects/${var.project_id}/databases/${var.firestore_database}"
|
|
to = google_firestore_database.c2
|
|
}
|
|
|
|
resource "google_firestore_database" "c2" {
|
|
project = var.project_id
|
|
name = var.firestore_database
|
|
location_id = var.firestore_location
|
|
type = "FIRESTORE_NATIVE"
|
|
|
|
# Prevent accidental deletion of the live database
|
|
deletion_policy = "DELETE"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# GCS bucket — audio recordings. Import existing bucket.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
import {
|
|
id = var.audio_bucket_name
|
|
to = google_storage_bucket.audio
|
|
}
|
|
|
|
resource "google_storage_bucket" "audio" {
|
|
project = var.project_id
|
|
name = var.audio_bucket_name
|
|
location = var.audio_bucket_location
|
|
uniform_bucket_level_access = true
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# DNS — managed in AWS Route 53 (cusano.net is there).
|
|
# After terraform apply, add these A records in Route 53:
|
|
# app.drb.cusano.net → server_ip output
|
|
# api.drb.cusano.net → server_ip output
|
|
# Or use a single wildcard: *.drb.cusano.net → server_ip
|
|
# ---------------------------------------------------------------------------
|