added technitium config
This commit is contained in:
1 parent
d4780d8dc9
commit
423caa9ca4
4 files changed
+90
-3
No files matched your search
@@ -1,10 +1,22 @@
|
|||||||
resource "local_sensitive_file" "ssh_private_key" {
|
resource "local_sensitive_file" "ssh_private_key" {
|
||||||
filename = "${path.module}/.ssh_key"
|
filename = pathexpand("~/.ssh/infra_ansible_key")
|
||||||
content_base64 = data.external.infisical.result["ssh_private_key_b64"]
|
content_base64 = data.external.infisical.result["ssh_private_key_b64"]
|
||||||
file_permission = "0600"
|
file_permission = "0600"
|
||||||
}
|
}
|
||||||
|
|
||||||
locals {
|
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 = try(data.external.infisical.result["technitium_api_token"], "") != ""
|
||||||
|
|
||||||
# Shared inputs passed to every proxmox_node module call.
|
# Shared inputs passed to every proxmox_node module call.
|
||||||
node_common = {
|
node_common = {
|
||||||
search_domain = var.search_domain
|
search_domain = var.search_domain
|
||||||
@@ -12,6 +24,7 @@ locals {
|
|||||||
ssh_key = data.external.infisical.result["ssh_public_key"]
|
ssh_key = data.external.infisical.result["ssh_public_key"]
|
||||||
ansible_user = var.ansible_user
|
ansible_user = var.ansible_user
|
||||||
lxc_password = data.external.infisical.result["lxc_password"]
|
lxc_password = data.external.infisical.result["lxc_password"]
|
||||||
|
ssh_private_key_path = local_sensitive_file.ssh_private_key.filename
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +45,7 @@ module "proxmox" {
|
|||||||
ssh_key = local.node_common.ssh_key
|
ssh_key = local.node_common.ssh_key
|
||||||
ansible_user = local.node_common.ansible_user
|
ansible_user = local.node_common.ansible_user
|
||||||
lxc_password = local.node_common.lxc_password
|
lxc_password = local.node_common.lxc_password
|
||||||
|
ssh_private_key_path = local.node_common.ssh_private_key_path
|
||||||
|
|
||||||
providers = {
|
providers = {
|
||||||
proxmox = proxmox.proxmox
|
proxmox = proxmox.proxmox
|
||||||
@@ -68,6 +82,16 @@ locals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
resource "local_file" "ansible_inventory" {
|
resource "local_file" "ansible_inventory" {
|
||||||
filename = "${path.module}/${var.ansible_inventory_path}"
|
filename = "${path.module}/${var.ansible_inventory_path}"
|
||||||
content = templatefile("${path.module}/opentofu/inventory.tpl", {
|
content = templatefile("${path.module}/opentofu/inventory.tpl", {
|
||||||
|
|||||||
@@ -8,7 +8,19 @@ terraform {
|
|||||||
source = "hashicorp/local"
|
source = "hashicorp/local"
|
||||||
version = "~> 2.2"
|
version = "~> 2.2"
|
||||||
}
|
}
|
||||||
|
technitium = {
|
||||||
|
source = "kenske/technitium"
|
||||||
|
version = "~> 0.2"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "technitium" {
|
||||||
|
host = var.technitium_host
|
||||||
|
# Fall back to a placeholder so the provider passes its credential check on
|
||||||
|
# the first run (before the token exists in Infisical). No technitium
|
||||||
|
# resources are created while the token is absent, so the dummy is never used.
|
||||||
|
token = coalesce(try(data.external.infisical.result["technitium_api_token"], ""), "token-not-yet-provisioned")
|
||||||
}
|
}
|
||||||
|
|
||||||
data "external" "infisical" {
|
data "external" "infisical" {
|
||||||
|
|||||||
+25
-2
@@ -16,8 +16,31 @@ network_subnets = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ansible_user = "ansible"
|
ansible_user = "ansible"
|
||||||
search_domain = "lan.oswaldtheotter.net"
|
search_domain = "oswaldtheotter.lan"
|
||||||
dns_nameservers = "1.1.1.1"
|
dns_nameservers = "1.1.1.1"
|
||||||
|
technitium_host = "http://192.168.0.2:5380"
|
||||||
|
|
||||||
|
# ── DNS (Technitium) ────────────────────────────────────────────────────────────
|
||||||
|
# Every declared node automatically gets an A record in the search_domain zone
|
||||||
|
# (lan.oswaldtheotter.net). Define extra zones and manual records below.
|
||||||
|
|
||||||
|
# Additional zones beyond the auto-managed search_domain zone.
|
||||||
|
dns_zones = {
|
||||||
|
# "internal.oswaldtheotter.net" = { type = "Primary" }
|
||||||
|
# "10.168.192.in-addr.arpa" = { type = "Primary" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Manual records. In the search_domain zone, a record whose name matches an
|
||||||
|
# auto-added host replaces that host's record instead of conflicting with it.
|
||||||
|
dns_records = [
|
||||||
|
# { zone = "lan.oswaldtheotter.net", name = "router", type = "A", value = "192.168.0.1" },
|
||||||
|
# { zone = "lan.oswaldtheotter.net", name = "nas", type = "CNAME", value = "dev.lan.oswaldtheotter.net" },
|
||||||
|
# { zone = "lan.oswaldtheotter.net", name = "@", type = "MX", value = "mail.lan.oswaldtheotter.net", priority = 10 },
|
||||||
|
{ zone = "oswaldtheotter.lan", name = "omada", type = "A", value = "192.168.0.110" },
|
||||||
|
{ zone = "oswaldtheotter.lan", name = "portanas", type = "A", value = "192.168.0.4" },
|
||||||
|
{ zone = "oswaldtheotter.lan", name = "proxmox", type = "A", value = "192.168.0.240" },
|
||||||
|
{ zone = "oswaldtheotter.lan", name = "nas", type = "CNAME", value = "portanas.lan.oswaldtheotter.net" },
|
||||||
|
]
|
||||||
|
|
||||||
# ── Node definitions ───────────────────────────────────────────────────────────
|
# ── Node definitions ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -77,7 +100,7 @@ nodes = {
|
|||||||
disk_size = "8G"
|
disk_size = "8G"
|
||||||
nic_name = "eth0"
|
nic_name = "eth0"
|
||||||
bridge = "vmbr0"
|
bridge = "vmbr0"
|
||||||
ip = "192.168.0.3/24"
|
ip = "192.168.0.2/24"
|
||||||
gw = "192.168.0.1"
|
gw = "192.168.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,34 @@ variable "dns_nameservers" {
|
|||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "technitium_host" {
|
||||||
|
description = "URL of the Technitium DNS Server API (e.g. http://192.168.0.3:5380). Required once Technitium is running."
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "dns_zones" {
|
||||||
|
description = "Additional Technitium DNS zones to create, beyond the auto-managed search_domain zone. Keyed by zone name."
|
||||||
|
type = map(object({
|
||||||
|
type = optional(string, "Primary")
|
||||||
|
forwarder = optional(string)
|
||||||
|
}))
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "dns_records" {
|
||||||
|
description = "Manually managed DNS records. Each targets a zone by name (the search_domain zone or one from dns_zones). A record in the search_domain zone whose name matches an auto-added host replaces that host record instead of conflicting with it."
|
||||||
|
type = list(object({
|
||||||
|
zone = string
|
||||||
|
name = string # subdomain label, or "@" for the zone apex
|
||||||
|
type = string # A, AAAA, CNAME, NS, TXT, MX
|
||||||
|
value = string # IP / target / text / mail exchanger
|
||||||
|
ttl = optional(number)
|
||||||
|
priority = optional(number) # required for MX records
|
||||||
|
}))
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
variable "ansible_inventory_path" {
|
variable "ansible_inventory_path" {
|
||||||
description = "Path where the generated Ansible inventory file is written. Defaults to ../ansible/inventories/generated.yml relative to this module, which points to the parent repo when used as a git submodule."
|
description = "Path where the generated Ansible inventory file is written. Defaults to ../ansible/inventories/generated.yml relative to this module, which points to the parent repo when used as a git submodule."
|
||||||
type = string
|
type = string
|
||||||
|
|||||||
Reference in new issue
Block a user