refactor(tofu): extract variables into their own files

The .tfvars files are normally gitignored, but they serve as an example here. Just need to make sure I don't commit a secret...

Inpired by #236
This commit is contained in:
Vegard Hagen
2025-03-23 17:19:46 +01:00
parent 1cf6031a53
commit 737e047c8e
24 changed files with 313 additions and 231 deletions
+2 -2
View File
@@ -9,8 +9,8 @@ output
*.tfstate
*.tfstate.*
*.tfvars
*.tfvars.json
*secret*.tfvars
*secret*.tfvars.json
*.lock.hcl
+2 -2
View File
@@ -16,8 +16,8 @@ resource "null_resource" "haos_image" {
resource "proxmox_virtual_environment_file" "haos_generic_image" {
depends_on = [null_resource.haos_image]
node_name = var.proxmox_node.name
datastore_id = var.proxmox_node.image_datastore
node_name = var.proxmox_cluster.name
datastore_id = var.proxmox_cluster.image_datastore
content_type = "iso"
+4 -4
View File
@@ -8,12 +8,12 @@ terraform {
}
provider "proxmox" {
endpoint = var.proxmox_node.endpoint
insecure = var.proxmox_node.insecure
endpoint = var.proxmox_cluster.endpoint
insecure = var.proxmox_cluster.insecure
api_token = var.proxmox_node.api_token
api_token = var.proxmox_api_token
ssh {
agent = true
username = var.proxmox_node.username
username = var.proxmox_cluster.username
}
}
@@ -0,0 +1,9 @@
proxmox_cluster = {
name = "abel"
endpoint = "https://192.168.1.62:8006"
insecure = true
username = "root"
image_datastore = "local"
}
haos_version = "12.4"
+5 -2
View File
@@ -1,12 +1,15 @@
variable "proxmox_node" {
variable "proxmox_cluster" {
type = object({
name = string
endpoint = string
insecure = bool
username = string
api_token = string
image_datastore = string
})
}
variable "proxmox_api_token" {
type = string
sensitive = true
}
+1 -1
View File
@@ -1,5 +1,5 @@
resource "proxmox_virtual_environment_vm" "home_assistant" {
node_name = var.proxmox_node.name
node_name = var.proxmox_cluster.name
name = "Home-Assistant"
description = "Managed by OpenTofu"
+32
View File
@@ -4,3 +4,35 @@
tofu output -raw kube_config
tofu output -raw talos_config
```
## Proxmox
Environment variable
```shell
export TF_VAR_proxmox_api_token="<YOUR_API_TOKEN>"
```
## Sealed-secrets
Generate certificate
```shell
openssl req -x509 -days 365 -nodes -newkey rsa:4096 -keyout sealed-secrets.key -out sealed-secrets.crt -subj "/CN=sealed-secret/O=sealed-secret"
```
## Kubernetes
Output `kubeconfig`
```shell
tofu output -raw kube_config
```
## Talos
Output `talosconfig`
```shell
tofu output -raw talos_config
```
@@ -17,7 +17,7 @@ resource "kubernetes_secret" "sealed-secrets-key" {
}
data = {
"tls.crt" = var.cert.cert
"tls.key" = var.cert.key
"tls.crt" = file("${path.root}/${var.cert.certificate_path}")
"tls.key" = file("${path.root}/${var.cert.certificate_key_path}")
}
}
@@ -1,6 +1,6 @@
variable "cert" {
type = object({
cert = string
key = string
certificate_path = string
certificate_key_path = string
})
}
@@ -6,7 +6,6 @@ module "proxmox-volume" {
restapi = restapi
}
proxmox_api = var.proxmox_api
volume = {
name = each.key
node = each.value.node
@@ -1,12 +1,3 @@
variable "proxmox_api" {
type = object({
endpoint = string
insecure = bool
api_token = string
})
sensitive = true
}
variable "volume" {
type = object({
name = string
@@ -2,10 +2,8 @@ variable "proxmox_api" {
type = object({
endpoint = string
insecure = bool
api_token = string
cluster_name = string
})
sensitive = true
}
variable "volumes" {
@@ -0,0 +1,58 @@
kubernetes_volumes = {
pv-sonarr = {
node = "cantor"
size = "4G"
}
pv-radarr = {
node = "cantor"
size = "4G"
}
pv-lidarr = {
node = "cantor"
size = "4G"
}
pv-prowlarr = {
node = "euclid"
size = "1G"
}
pv-torrent = {
node = "euclid"
size = "1G"
}
pv-remark42 = {
node = "euclid"
size = "1G"
}
pv-authelia-postgres = {
node = "euclid"
size = "2G"
}
pv-lldap-postgres = {
node = "euclid"
size = "2G"
}
pv-keycloak-postgres = {
node = "euclid"
size = "2G"
}
pv-jellyfin = {
node = "euclid"
size = "12G"
}
pv-netbird-signal = {
node = "abel"
size = "512M"
}
pv-netbird-management = {
node = "abel"
size = "512M"
}
pv-plex = {
node = "abel"
size = "12G"
}
pv-prometheus = {
node = "abel"
size = "10G"
}
}
+7 -138
View File
@@ -5,81 +5,10 @@ module "talos" {
proxmox = proxmox
}
image = {
version = "v1.9.2"
update_version = "v1.9.3" # renovate: github-releases=siderolabs/talos
schematic = file("${path.module}/talos/image/schematic.yaml")
# Point this to a new schematic file to update the schematic
update_schematic = file("${path.module}/talos/image/schematic.yaml")
}
cilium = {
values = file("${path.module}/../../k8s/infra/network/cilium/values.yaml")
install = file("${path.module}/talos/inline-manifests/cilium-install.yaml")
}
cluster = {
name = "talos"
# This should point to the vip as below(if nodes on layer 2) or one of the nodes (if nodes not on layer 2)
# Note: Nodes are not on layer 2 if there is a router between them (even a mesh router)
# Not sure how it works if connected to the same router via ethernet (does it act as a switch then???)
# Ref: https://www.talos.dev/v1.9/talos-guides/network/vip/#requirements
# Note This is Kubernetes API endpoint. Different from all mentions of Talos endpoints.
endpoint = "192.168.1.102"
vip = "192.168.1.99"
gateway = "192.168.1.1"
# The version of talos features to use in generated machine configuration. Generally the same as image version.
# See https://github.com/siderolabs/terraform-provider-talos/blob/main/docs/data-sources/machine_configuration.md
talos_machine_config_version = "v1.9.2"
proxmox_cluster = "homelab"
kubernetes_version = "1.32.0" # renovate: github-releases=kubernetes/kubernetes
base_domain = "stonegarden.dev"
}
nodes = {
"ctrl-00" = {
host_node = "abel"
machine_type = "controlplane"
ip = "192.168.1.100"
#dns = ["1.1.1.1", "8.8.8.8"] # Optional Value.
mac_address = "BC:24:11:2E:C8:00"
vm_id = 800
cpu = 8
ram_dedicated = 28672
igpu = true
}
"ctrl-01" = {
host_node = "euclid"
machine_type = "controlplane"
ip = "192.168.1.101"
mac_address = "BC:24:11:2E:C8:01"
vm_id = 801
cpu = 4
ram_dedicated = 20480
igpu = true
#update = true
}
"ctrl-02" = {
host_node = "cantor"
machine_type = "controlplane"
ip = "192.168.1.102"
mac_address = "BC:24:11:2E:C8:02"
vm_id = 802
cpu = 4
ram_dedicated = 4096
#update = true
}
# "work-00" = {
# host_node = "abel"
# machine_type = "worker"
# ip = "192.168.1.110"
# mac_address = "BC:24:11:2E:A8:00"
# vm_id = 810
# cpu = 8
# ram_dedicated = 4096
# }
}
image = var.talos_image
cluster = var.talos_cluster_config
cilium = var.cilium_config
nodes = var.talos_nodes
}
module "sealed_secrets" {
@@ -90,11 +19,7 @@ module "sealed_secrets" {
kubernetes = kubernetes
}
// openssl req -x509 -days 365 -nodes -newkey rsa:4096 -keyout sealed-secrets.key -out sealed-secrets.crt -subj "/CN=sealed-secret/O=sealed-secret"
cert = {
cert = file("${path.module}/bootstrap/sealed-secrets/certificate/sealed-secrets.crt")
key = file("${path.module}/bootstrap/sealed-secrets/certificate/sealed-secrets.key")
}
cert = var.sealed_secrets_config
}
module "proxmox_csi_plugin" {
@@ -117,63 +42,7 @@ module "volumes" {
restapi = restapi
kubernetes = kubernetes
}
proxmox_api = var.proxmox
volumes = {
pv-sonarr = {
node = "cantor"
size = "4G"
}
pv-radarr = {
node = "cantor"
size = "4G"
}
pv-lidarr = {
node = "cantor"
size = "4G"
}
pv-prowlarr = {
node = "euclid"
size = "1G"
}
pv-torrent = {
node = "euclid"
size = "1G"
}
pv-remark42 = {
node = "euclid"
size = "1G"
}
pv-authelia-postgres = {
node = "euclid"
size = "2G"
}
pv-lldap-postgres = {
node = "euclid"
size = "2G"
}
pv-keycloak-postgres = {
node = "euclid"
size = "2G"
}
pv-jellyfin = {
node = "euclid"
size = "12G"
}
pv-netbird-signal = {
node = "abel"
size = "512M"
}
pv-netbird-management = {
node = "abel"
size = "512M"
}
pv-plex = {
node = "abel"
size = "12G"
}
pv-prometheus = {
node = "abel"
size = "10G"
}
}
volumes = var.kubernetes_volumes
}
+2 -2
View File
@@ -23,7 +23,7 @@ provider "proxmox" {
endpoint = var.proxmox.endpoint
insecure = var.proxmox.insecure
api_token = var.proxmox.api_token
api_token = var.proxmox_api_token
ssh {
agent = true
username = var.proxmox.username
@@ -37,7 +37,7 @@ provider "restapi" {
headers = {
"Content-Type" = "application/json"
"Authorization" = "PVEAPIToken=${var.proxmox.api_token}"
"Authorization" = "PVEAPIToken=${var.proxmox_api_token}"
}
}
+7
View File
@@ -0,0 +1,7 @@
proxmox = {
name = "abel"
cluster_name = "homelab"
endpoint = "https://192.168.1.62:8006"
insecure = true
username = "root"
}
@@ -0,0 +1,4 @@
sealed_secrets_config = {
certificate_path = "bootstrap/sealed-secrets/certificate/sealed-secrets.crt"
certificate_key_path = "bootstrap/sealed-secrets/certificate/sealed-secrets.key"
}
+2 -2
View File
@@ -34,8 +34,8 @@ data "talos_machine_configuration" "this" {
vip = var.cluster.vip
}), each.value.machine_type == "controlplane" ?
templatefile("${path.module}/machine-config/control-plane.yaml.tftpl", {
cilium_values = var.cilium.values
cilium_install = var.cilium.install
cilium_values = file("${path.root}/${var.cilium.values_path}")
cilium_install = file("${path.root}/${var.cilium.install_manifest_path}")
base_domain = var.cluster.base_domain
}) : ""
]
+3 -4
View File
@@ -1,10 +1,11 @@
locals {
version = var.image.version
schematic = var.image.schematic
schematic = file("${path.root}/${var.image.schematic_path}")
schematic_id = jsondecode(data.http.schematic_id.response_body)["id"]
update_version = coalesce(var.image.update_version, var.image.version)
update_schematic = coalesce(var.image.update_schematic, var.image.schematic)
update_schematic_path = coalesce(var.image.update_schematic_path, var.image.schematic_path)
update_schematic = file("${path.root}/${local.update_schematic_path}")
update_schematic_id = jsondecode(data.http.updated_schematic_id.response_body)["id"]
image_id = "${local.schematic_id}_${local.version}"
@@ -14,8 +15,6 @@ locals {
# ref - https://github.com/vehagn/homelab/issues/106
# image_id = "${talos_image_factory_schematic.this.id}_${local.version}"
# update_image_id = "${talos_image_factory_schematic.updated.id}_${local.update_version}"
}
data "http" "schematic_id" {
+4 -4
View File
@@ -2,9 +2,9 @@ variable "image" {
description = "Talos image configuration"
type = object({
factory_url = optional(string, "https://factory.talos.dev")
schematic = string
schematic_path = string
version = string
update_schematic = optional(string)
update_schematic_path = optional(string)
update_version = optional(string)
arch = optional(string, "amd64")
platform = optional(string, "nocloud")
@@ -47,7 +47,7 @@ variable "nodes" {
variable "cilium" {
description = "Cilium configuration"
type = object({
values = string
install = string
install_manifest_path = string
values_path = string
})
}
+22
View File
@@ -0,0 +1,22 @@
talos_cluster_config = {
name = "talos"
# This should point to the vip as below(if nodes on layer 2) or one of the nodes (if nodes not on layer 2)
# Note: Nodes are not on layer 2 if there is a router between them (even a mesh router)
# Not sure how it works if connected to the same router via ethernet (does it act as a switch then???)
# Ref: https://www.talos.dev/v1.9/talos-guides/network/vip/#requirements
# Note This is Kubernetes API endpoint. Different from all mentions of Talos endpoints.
endpoint = "192.168.1.102"
vip = "192.168.1.99"
gateway = "192.168.1.1"
# The version of talos features to use in generated machine configuration. Generally the same as image version.
# See https://github.com/siderolabs/terraform-provider-talos/blob/main/docs/data-sources/machine_configuration.md
talos_machine_config_version = "v1.9.2"
proxmox_cluster = "homelab"
kubernetes_version = "1.32.0" # renovate: github-releases=kubernetes/kubernetes
base_domain = "stonegarden.dev"
}
cilium_config = {
values_path = "../../k8s/infra/network/cilium/values.yaml"
install_manifest_path = "talos/inline-manifests/cilium-install.yaml"
}
+7
View File
@@ -0,0 +1,7 @@
talos_image = {
version = "v1.9.2"
update_version = "v1.9.3" # renovate: github-releases=siderolabs/talos
schematic_path = "talos/image/schematic.yaml"
# Point this to a new schematic file to update the schematic
# update_schematic_path = "talos/image/schematic.yaml"
}
+43
View File
@@ -0,0 +1,43 @@
talos_nodes = {
"ctrl-00" = {
host_node = "abel"
machine_type = "controlplane"
ip = "192.168.1.100"
#dns = ["1.1.1.1", "8.8.8.8"] # Optional Value.
mac_address = "BC:24:11:2E:C8:00"
vm_id = 800
cpu = 8
ram_dedicated = 28672
igpu = true
}
"ctrl-01" = {
host_node = "euclid"
machine_type = "controlplane"
ip = "192.168.1.101"
mac_address = "BC:24:11:2E:C8:01"
vm_id = 801
cpu = 4
ram_dedicated = 20480
igpu = true
#update = true
}
"ctrl-02" = {
host_node = "cantor"
machine_type = "controlplane"
ip = "192.168.1.102"
mac_address = "BC:24:11:2E:C8:02"
vm_id = 802
cpu = 4
ram_dedicated = 4096
#update = true
}
# "work-00" = {
# host_node = "abel"
# machine_type = "worker"
# ip = "192.168.1.110"
# mac_address = "BC:24:11:2E:A8:00"
# vm_id = 810
# cpu = 8
# ram_dedicated = 4096
# }
}
+84 -43
View File
@@ -1,54 +1,95 @@
variable "proxmox" {
description = "Proxmox provider configuration"
type = object({
name = string
cluster_name = string
endpoint = string
insecure = bool
username = string
api_token = string
})
}
variable "proxmox_api_token" {
description = "API token for Proxmox"
type = string
sensitive = true
}
#variable "cluster_config" {
# description = "Talos node configuration"
# type = object({
#
# cluster_name = string
# proxmox_cluster = string
# endpoint = string
# talos_version = string
#
# nodes = map(
# object({
# host_node = string
# machine_type = string
# ip = string
# mac_address = string
# vm_id = number
# cpu = number
# ram_dedicated = number
# update = optional(bool, false)
# igpu = optional(bool, false)
# })
# )
# })
#
# validation {
# condition = length([
# for n in var.cluster_config.nodes : n if contains(["controlplane", "worker"], n.machine_type)]) == length(var.cluster_config.nodes)
# error_message = "Node machine_type must be either 'controlplane' or 'worker'."
# }
#}
#
#variable "volumes" {
# type = map(
# object({
# node = string
# size = string
# storage = optional(string, "local-zfs")
# vmid = optional(number, 9999)
# format = optional(string, "raw")
# })
# )
#}
variable "talos_image" {
description = "Talos image configuration"
type = object({
factory_url = optional(string, "https://factory.talos.dev")
version = string
schematic_path = string
update_version = optional(string)
update_schematic_path = optional(string)
arch = optional(string, "amd64")
platform = optional(string, "nocloud")
proxmox_datastore = optional(string, "local")
})
}
variable "talos_cluster_config" {
description = "Talos cluster configuration"
type = object({
name = string
endpoint = string
vip = optional(string)
gateway = string
talos_machine_config_version = optional(string)
proxmox_cluster = string
kubernetes_version = string
base_domain = string
})
}
variable "cilium_config" {
description = "Path to Cilium installation manifest and configuration values"
type = object({
install_manifest_path = string
values_path = string
})
}
variable "talos_nodes" {
type = map(
object({
host_node = string
machine_type = string
ip = string
dns = optional(list(string))
mac_address = string
vm_id = number
cpu = number
ram_dedicated = number
update = optional(bool, false)
igpu = optional(bool, false)
})
)
validation {
// @formatter:off
condition = length([for n in var.talos_nodes : n if contains(["controlplane", "worker"], n.machine_type)]) == length(var.talos_nodes)
error_message = "Node machine_type must be either 'controlplane' or 'worker'."
// @formatter:on
}
}
variable "sealed_secrets_config" {
description = "Sealed-secrets configuration"
type = object({
certificate_path = string
certificate_key_path = string
})
}
variable "kubernetes_volumes" {
type = map(
object({
node = string
size = string
storage = optional(string, "local-zfs")
vmid = optional(number, 9999)
format = optional(string, "raw")
})
)
}