terraform { required_providers { digitalocean = { source = "digitalocean/digitalocean" version = "2.62.0" } ct = { source = "poseidon/ct" version = "0.13.0" } null = { source = "hashicorp/null" version = "3.2.4" } time = { source = "hashicorp/time" version = "0.13.1" } cloudflare = { source = "cloudflare/cloudflare" version = "5.8.2" } } } variable "do_token" { description = "DigitalOcean token" type = string } variable "machines" { type = list(string) description = "Machine names, corresponding to machine-NAME.yaml.tmpl files" } variable "cluster_name" { type = string description = "Cluster name used as prefix for the machine names" } variable "ssh_keys" { type = list(string) description = "SSH public keys for user 'core' (and to register on Digital Ocean for the first)" } variable "server_type" { type = string default = "s-1vcpu-1gb" description = "The server type to rent" } variable "datacenter" { type = string description = "The region to deploy in" } variable "flatcar_stable_version" { type = string description = "The Flatcar Stable release you want to use for the initial installation, e.g., 2605.12.0" } variable "cloudflare_zone_id" { type = string description = "Cloudflare zone ID" } variable "cloudflare_account_id" { type = string description = "Cloudflare account id" } variable "cloudflare_api_token" { type = string description = "Cloudflare api token" } variable "domain" { type = string description = "Root domain to use" } provider "digitalocean" { token = var.do_token } provider "cloudflare" { api_token = var.cloudflare_api_token } resource "digitalocean_ssh_key" "first" { name = var.cluster_name public_key = var.ssh_keys.0 } resource "digitalocean_custom_image" "flatcar" { name = "flatcar-stable-${var.flatcar_stable_version}" url = "https://stable.release.flatcar-linux.net/amd64-usr/${var.flatcar_stable_version}/flatcar_production_digitalocean_image.bin.bz2" regions = [var.datacenter] } resource "digitalocean_reserved_ip" "machine" { for_each = toset(var.machines) region = digitalocean_droplet.machine[each.key].region } resource "cloudflare_dns_record" "machine" { for_each = toset(var.machines) zone_id = var.cloudflare_zone_id name = "${var.cluster_name}-${each.key}" content = digitalocean_reserved_ip.machine[each.key].ip_address type = "A" proxied = false ttl = 300 } resource "digitalocean_volume" "machine" { for_each = toset(var.machines) region = var.datacenter name = "${var.cluster_name}-${each.key}" size = 30 initial_filesystem_type = "ext4" initial_filesystem_label = "appstorage" description = "persistent storage for docker apps" } resource "digitalocean_droplet" "machine" { for_each = toset(var.machines) name = "${var.cluster_name}-${each.key}" image = digitalocean_custom_image.flatcar.id region = var.datacenter size = var.server_type ssh_keys = [digitalocean_ssh_key.first.fingerprint] # user_data = data.ct_config.machine-ignitions[each.key].rendered user_data = file("flatcar/ignition.json") lifecycle { create_before_destroy = true } } resource "time_sleep" "wait_5_seconds" { create_duration = "5s" } resource "digitalocean_reserved_ip_assignment" "machine" { for_each = toset(var.machines) ip_address = digitalocean_reserved_ip.machine[each.key].ip_address droplet_id = digitalocean_droplet.machine[each.key].id # sometimes digital ocean throws an error for this resource # saying the droplet has a pending event so we delay a few seconds depends_on = [time_sleep.wait_5_seconds] } resource "digitalocean_volume_attachment" "machine" { for_each = toset(var.machines) droplet_id = digitalocean_droplet.machine[each.key].id volume_id = digitalocean_volume.machine[each.key].id } # data "ct_config" "machine-ignitions" { # for_each = toset(var.machines) # content = templatefile("${path.module}/cl/machine-${each.key}.yaml.tmpl", { # ssh_keys = jsonencode(var.ssh_keys), # name = each.key # }) # strict = true # } # output "ip-addresses" { # value = { # for key in var.machines : # "${var.cluster_name}-${key}" => digitalocean_droplet.machine[key].ipv4_address # } # } output "domain-mappings" { value = { for key in var.machines : "${var.cluster_name}-${key}.${var.domain}" => digitalocean_reserved_ip.machine[key].ip_address } }