############################################################################### # Shared services droplet — 3 Forgejo instances (ct/mc/quinn) + Verdaccio, # co-located. Public-facing (like the current ct-forge). 4GB + swap (tight but # fine for low-traffic git + npm). PyPI / SwiftPM / DNS / Caddy are fast-follow. ############################################################################### resource "digitalocean_droplet" "services" { name = var.name image = "ubuntu-24-04-x64" size = var.droplet_size region = var.region ssh_keys = var.ssh_key_fingerprints tags = ["services", "forge", "quinn-infra"] user_data = file("${path.module}/cloud-init.yaml") lifecycle { # Forgejo/Verdaccio data lives in /opt/services volumes; never let a # user_data tweak silently rebuild and wipe it. ignore_changes = [user_data] } } resource "digitalocean_firewall" "services" { name = "services-fw" droplet_ids = [digitalocean_droplet.services.id] inbound_rule { protocol = "tcp" port_range = "22" source_addresses = ["0.0.0.0/0", "::/0"] } # Forgejo HTTP (ct 3000 / mc 3001 / quinn 3002) + git-SSH (2222/2223/2224) + Verdaccio 4873 inbound_rule { protocol = "tcp" port_range = "3000-3002" source_addresses = ["0.0.0.0/0", "::/0"] } inbound_rule { protocol = "tcp" port_range = "2222-2224" source_addresses = ["0.0.0.0/0", "::/0"] } inbound_rule { protocol = "tcp" port_range = "4873" source_addresses = ["0.0.0.0/0", "::/0"] } # 80/443 for future Caddy/TLS inbound_rule { protocol = "tcp" port_range = "80" source_addresses = ["0.0.0.0/0", "::/0"] } inbound_rule { protocol = "tcp" port_range = "443" source_addresses = ["0.0.0.0/0", "::/0"] } outbound_rule { protocol = "tcp" port_range = "1-65535" destination_addresses = ["0.0.0.0/0", "::/0"] } outbound_rule { protocol = "udp" port_range = "1-65535" destination_addresses = ["0.0.0.0/0", "::/0"] } outbound_rule { protocol = "icmp" destination_addresses = ["0.0.0.0/0", "::/0"] } } output "services_ip" { value = digitalocean_droplet.services.ipv4_address } output "forge_urls" { value = { ct = "http://${digitalocean_droplet.services.ipv4_address}:3000" mc = "http://${digitalocean_droplet.services.ipv4_address}:3001" quinn = "http://${digitalocean_droplet.services.ipv4_address}:3002" npm = "http://${digitalocean_droplet.services.ipv4_address}:4873" } }