Files

171 lines
5.9 KiB
Terraform

resource "local_sensitive_file" "ssh_private_key" {
filename = pathexpand("~/.ssh/infra_ansible_key")
content_base64 = data.external.infisical.result["ssh_private_key_b64"]
file_permission = "0600"
}
locals {
# Flatten all declared hosts from tfvars. Derived from var.nodes (not module
# outputs) so the values are known at plan time and for_each can use them
# before any VMs are created.
all_declared_hosts = flatten([
for hv_name, hv in var.nodes : concat(
[for name, lxc in try(hv.lxc, {}) : { name = name, ip = split("/", lxc.ip)[0] }],
[for name, vm in try(hv.machines, {}) : { name = name, ip = split("/", vm.ip)[0] }],
[for name, fc in try(hv.flatcar, {}) : { name = name, ip = fc.ip }]
)
])
technitium_enabled = var.technitium_enabled && try(data.external.infisical.result["technitium_api_token"], "") != ""
ipam_enabled = try(data.external.infisical.result["ipam_username"], "") != ""
caddy_enabled = var.caddy_host != ""
# Shared inputs passed to every proxmox_node module call.
node_common = {
search_domain = var.search_domain
dns_nameservers = var.dns_nameservers
ssh_key = data.external.infisical.result["ssh_public_key"]
ansible_user = var.ansible_user
lxc_password = data.external.infisical.result["lxc_password"]
ssh_private_key_path = local_sensitive_file.ssh_private_key.filename
}
}
# Provider aliases must be statically declared, so each hypervisor needs its
# own module block. To add or remove a hypervisor, add/remove the corresponding
# provider alias in providers.tf and a module block here. Everything else
# (node contents, common config) lives in the parent repo's terraform.tfvars.
# butane/versions-sync.yaml goes onto every Flatcar VM through its inline
# butane field (the module merges it with butane_file). Inline snippets are
# not templated, so the file is read as-is. No VM sets butane in tfvars; one
# that did would replace this snippet, not add to it, and lose version sync.
locals {
flatcar_common_butane = file("${path.module}/butane/versions-sync.yaml")
flatcar_with_common = {
for hv in ["proxmox", "goose"] : hv => {
for name, vm in try(var.nodes[hv].flatcar, {}) :
name => merge(vm, { butane = coalesce(vm.butane, local.flatcar_common_butane) })
}
}
}
module "proxmox" {
source = "./opentofu/modules/proxmox_node"
node_name = var.hypervisors["proxmox"].node_name
storage = var.hypervisors["proxmox"].storage
lxc = try(var.nodes["proxmox"].lxc, {})
machines = try(var.nodes["proxmox"].machines, {})
flatcar = local.flatcar_with_common["proxmox"]
search_domain = local.node_common.search_domain
dns_nameservers = local.node_common.dns_nameservers
ssh_key = local.node_common.ssh_key
ansible_user = local.node_common.ansible_user
lxc_password = local.node_common.lxc_password
ssh_private_key_path = local.node_common.ssh_private_key_path
flatcar_image = var.flatcar_image
snippets_datastore = var.snippets_datastore
butane_vars = data.external.infisical.result
providers = {
proxmox = proxmox.proxmox
}
}
module "goose" {
source = "./opentofu/modules/proxmox_node"
node_name = var.hypervisors["goose"].node_name
storage = var.hypervisors["goose"].storage
lxc = try(var.nodes["goose"].lxc, {})
machines = try(var.nodes["goose"].machines, {})
flatcar = local.flatcar_with_common["goose"]
search_domain = local.node_common.search_domain
dns_nameservers = local.node_common.dns_nameservers
ssh_key = local.node_common.ssh_key
ansible_user = local.node_common.ansible_user
lxc_password = local.node_common.lxc_password
ssh_private_key_path = local.node_common.ssh_private_key_path
flatcar_image = var.flatcar_image
snippets_datastore = var.snippets_datastore
butane_vars = data.external.infisical.result
providers = {
proxmox = proxmox.goose
}
}
locals {
hv_hosts = {
proxmox = { lxc = module.proxmox.lxc_hosts, vm = module.proxmox.vm_hosts, flatcar = module.proxmox.flatcar_hosts }
goose = { lxc = module.goose.lxc_hosts, vm = module.goose.vm_hosts, flatcar = module.goose.flatcar_hosts }
}
all_hosts = flatten([
for hv_name, hv in local.hv_hosts : [
for h in concat(hv.lxc, hv.vm, hv.flatcar) : [
for tag in h.filtered_tags : {
tag = tag
name = h.name
ip = h.ip
vmid = h.vmid
}
]
]
])
tag_groups = {
for tag in distinct([for h in local.all_hosts : h.tag]) :
tag => [
for h in local.all_hosts : {
name = h.name
ip = h.ip
vmid = h.vmid
} if h.tag == tag
]
}
}
# Uncomment when phpIPAM is running and credentials are in Infisical.
# module "phpipam" {
# source = "./opentofu/modules/phpipam"
#
# enabled = local.ipam_enabled
# hosts = local.all_declared_hosts
# network_subnets = var.network_subnets
# }
module "technitium" {
source = "./opentofu/modules/technitium"
enabled = local.technitium_enabled
zone = var.search_domain
hosts = local.all_declared_hosts
zones = var.dns_zones
records = var.dns_records
}
module "caddy" {
source = "./opentofu/modules/caddy"
enabled = local.caddy_enabled
proxies = var.caddy_proxies
providers = {
caddy = caddy
}
}
resource "local_file" "ansible_inventory" {
filename = "${path.module}/${var.ansible_inventory_path}"
content = templatefile("${path.module}/opentofu/inventory.tpl", {
hypervisors = local.hv_hosts
tag_groups = local.tag_groups
ansible_user = var.ansible_user
ansible_ssh_private_key_file = local_sensitive_file.ssh_private_key.filename
})
}