homelab/build/config/terraform/README.md
Russell Seymour 1250c9cef6
Some checks are pending
deploy / deploy (push) Waiting to run
Initial checkin of code for managing homelab
2026-08-24 20:52:36 +01:00

2.8 KiB

build/config/terraform

Centralized Terraform config for Proxmox — provider, backend, and the module calls that say what infrastructure exists. The counterpart to build/config/ansible, which holds inventory and the shared roles.

Division of labour

Terraform's job stops at the guest. It creates the LXC (template, cores, memory, disk, IP) and nothing more; Ansible then installs the app into it via the lxc_app role. That split is why Ansible is the common tool across both platforms and Terraform is Proxmox-only:

Unraid Proxmox
Provision the host n/a — it already exists Terraform (this directory)
Install the app Ansible + compose_stack (Docker Compose) Ansible + lxc_app (native + systemd)
App config src/<app>/common/vars.yml + src/<app>/ansible/unraid/vars.yml src/<app>/common/vars.yml + src/<app>/ansible/proxmox/vars.yml

Per-app LXC specs live in src/<app>/terraform/ as modules, called from main.tf here.

State

backend "pg" — specifically against the CloudNativePG cluster on the k3s Pis, reached on its MetalLB address (k3s_postgres_loadbalancer_ip, 192.168.50.81). Not the shared Postgres this configuration itself provisions on Proxmox, which would be circular: Terraform would need the database to exist in order to create the container the database runs in. State goes somewhere Terraform has no hand in building, which breaks the cycle outright. Local state would make Terraform workstation-only; CI needs to see the same state.

The connection string holds a password, so it is passed at init rather than committed:

terraform init \
  -backend-config="conn_str=postgres://terraform:$PG_PASSWORD@192.168.50.81:5432/terraform_state"

The bootstrap dependency this creates is on k3s, not Unraid: the cluster and its CNPG instance must be up, with a terraform_state database and a terraform role created on it, before terraform init works. That is the one cross-platform dependency the rest of the repo avoids, and it is deliberate — the alternative is a local-state-then-init -migrate-state dance that has to be got right exactly once. Ordering is in docs/postgres-proxmox.md.

Credentials

Proxmox API token and the Postgres connection string both come from Vault (homelab/ci/proxmox, homelab/ci/terraform), exported as environment variables before running — the same pattern group_vars/all.yml uses for VAULT_ADDR and friends. Nothing authenticating to anything is committed.

export TF_VAR_proxmox_endpoint='https://turtle-proxmox-01.home.turtlesystems.co.uk:8006/'
export TF_VAR_proxmox_api_token='root@pam!terraform=<secret>'

Status

Not yet applied against anything. The provider version is intentionally unpinned until the first terraform init — pin what it resolves and commit .terraform.lock.hcl (which is not gitignored).