Files
oswald-infra/main.tf
T
nickandClaude Opus 5 14dd42bb1b Add technitium_enabled toggle and turn DNS management off
module.technitium was gated only on the API token being present in
Infisical, so the single way to stop Terraform reconciling DNS was to pull
the token -- which also disables anything else that needs it. This adds an
explicit switch that ANDs with the existing token check, so the token can
stay put.

Set to false for now: DNS is being moved by hand during the domain
migration, and an apply in the middle of that would fight it.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 10:00:35 +00:00

148 lines
4.7 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] }]
)
])
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.
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, {})
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
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, {})
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
providers = {
proxmox = proxmox.goose
}
}
locals {
hv_hosts = {
proxmox = { lxc = module.proxmox.lxc_hosts, vm = module.proxmox.vm_hosts }
goose = { lxc = module.goose.lxc_hosts, vm = module.goose.vm_hosts }
}
all_hosts = flatten([
for hv_name, hv in local.hv_hosts : [
for h in concat(hv.lxc, hv.vm) : [
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
})
}