diff --git a/infra/main/main.tf b/infra/main/main.tf index c323877..c362e4a 100644 --- a/infra/main/main.tf +++ b/infra/main/main.tf @@ -13,6 +13,8 @@ resource "random_id" "suffix" { resource "digitalocean_custom_image" "talos" { name = "talos" url = "https://github.com/siderolabs/talos/releases/download/v1.4.3/digital-ocean-amd64.raw.gz" + # this gets reset by DigitalOcean + distribution = "Unknown OS" regions = [var.region] } @@ -31,5 +33,34 @@ module "digitalocean_talos_cluster-2" { count = 1, size = "s-2vcpu-4gb", }] - digitalocean_region = "sfo3" + digitalocean_region = var.region +} + +module "digitalocean_database_cluster" { + source = "../../terraform_modules/digitalocean_database_cluster" + + cluster_name = "distrust" + db_engine = "pg" + db_version = "15" + size = "db-s-1vcpu-2gb" + node_count = 1 + + databases = [{ + name = "keycloak", + create_default_superuser = true, + }, { + name = "forgejo", + create_default_superuser = true, + }] + + vpc_id = module.digitalocean_talos_cluster-2.vpc_id + digitalocean_region = var.region +} + +# TODO: make it output a Kubernetes Secret in env var format, can be piped into +# `jq .database_users.value.forgejo | sops --encrypt` for nice secret gen +# Ref: https://github.com/RyanSquared/gitops/blob/b8305292f215f6fe0bed170550b9b869302ab9e2/environments/production/kustomizations/forgejo/forgejo-config.enc.yaml +output "database_users" { + value = module.digitalocean_database_cluster.database_users + sensitive = true } diff --git a/terraform_modules/digitalocean_database_cluster/main.tf b/terraform_modules/digitalocean_database_cluster/main.tf new file mode 100644 index 0000000..217917b --- /dev/null +++ b/terraform_modules/digitalocean_database_cluster/main.tf @@ -0,0 +1,53 @@ +terraform { + required_providers { + digitalocean = { + source = "digitalocean/digitalocean" + version = "~> 2.0" + } + } +} + +resource "digitalocean_database_cluster" "main" { + name = var.cluster_name + engine = var.db_engine + size = var.size + region = var.digitalocean_region + node_count = var.node_count + version = var.db_version + private_network_uuid = var.vpc_id # TODO: nullable = true +} + +resource "digitalocean_database_db" "main" { + for_each = { for db in var.databases: db.name => db } + + cluster_id = digitalocean_database_cluster.main.id + name = each.key +} + +locals { + base_connection_string = trimsuffix(digitalocean_database_cluster.main.uri, + "/defaultdb?sslmode=require") +} + +resource "digitalocean_database_user" "default_users" { + for_each = { + for db in [for db in var.databases: db if db.create_default_superuser]: + db.name => db.name + } + + cluster_id = digitalocean_database_cluster.main.id + name = each.key + + provisioner "local-exec" { + command = "GRANT ALL ON DATABASE ${each.key} TO ${each.key}" + interpreter = ["psql", "${local.base_connection_string}/${each.key}"] + } + + provisioner "local-exec" { + command = "GRANT ALL ON SCHEMA public TO ${each.key}" + interpreter = ["psql", "${local.base_connection_string}/${each.key}"] + } + + # Note: provisioners depend on databases existing + depends_on = [digitalocean_database_db.main] +} diff --git a/terraform_modules/digitalocean_database_cluster/outputs.tf b/terraform_modules/digitalocean_database_cluster/outputs.tf new file mode 100644 index 0000000..9d68fbe --- /dev/null +++ b/terraform_modules/digitalocean_database_cluster/outputs.tf @@ -0,0 +1,7 @@ +output "database_cluster" { + value = digitalocean_database_cluster.main +} + +output "database_users" { + value = digitalocean_database_user.default_users +} diff --git a/terraform_modules/digitalocean_database_cluster/variables.tf b/terraform_modules/digitalocean_database_cluster/variables.tf new file mode 100644 index 0000000..dd1a6a3 --- /dev/null +++ b/terraform_modules/digitalocean_database_cluster/variables.tf @@ -0,0 +1,35 @@ +variable "cluster_name" { + type = string +} + +variable "db_engine" { + type = string +} + +variable "size" { + type = string +} + +variable "digitalocean_region" { + type = string +} + +variable "node_count" { + type = number +} + +variable "databases" { + type = list(object({ + name = string, + create_default_superuser = optional(bool, false), + })) +} + +variable "db_version" { + type = string +} + +variable "vpc_id" { + type = string + nullable = true +} diff --git a/terraform_modules/digitalocean_talos_cluster/outputs.tf b/terraform_modules/digitalocean_talos_cluster/outputs.tf new file mode 100644 index 0000000..5cd7239 --- /dev/null +++ b/terraform_modules/digitalocean_talos_cluster/outputs.tf @@ -0,0 +1,3 @@ +output "vpc_id" { + value = var.vpc_id == "undefined" ? digitalocean_vpc.talos[0].id : var.vpc_id +}