From ac41e3448e47a2e8eb9b089b16d55a8bc12ba1be Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 Apr 2026 20:08:11 -0500 Subject: [PATCH 1/6] feat: add bare bones Proxmox Terraform scaffold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds provider config, variables, and an example tfvars file using the bpg/proxmox provider. No resources are managed yet — existing Proxmox setup is untouched. Co-Authored-By: Claude Sonnet 4.6 --- main.tf | 19 +++++++++++++++++++ terraform.tfvars.example | 7 +++++++ variables.tf | 21 +++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 main.tf create mode 100644 terraform.tfvars.example create mode 100644 variables.tf diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..f990117 --- /dev/null +++ b/main.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "~> 0.73" + } + } +} + +provider "proxmox" { + endpoint = var.proxmox_endpoint + username = var.proxmox_username + password = var.proxmox_password + + # Set to true if using a self-signed certificate (common on home labs) + insecure = var.proxmox_insecure +} diff --git a/terraform.tfvars.example b/terraform.tfvars.example new file mode 100644 index 0000000..57efa2c --- /dev/null +++ b/terraform.tfvars.example @@ -0,0 +1,7 @@ +# Copy this file to terraform.tfvars and fill in your values. +# terraform.tfvars is gitignored to keep secrets out of version control. + +proxmox_endpoint = "https://192.168.1.10:8006/" +proxmox_username = "terraform@pve" +proxmox_password = "changeme" +proxmox_insecure = true diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..bb857a0 --- /dev/null +++ b/variables.tf @@ -0,0 +1,21 @@ +variable "proxmox_endpoint" { + description = "URL of the Proxmox API endpoint, e.g. https://192.168.1.10:8006/" + type = string +} + +variable "proxmox_username" { + description = "Proxmox user in the form user@realm, e.g. terraform@pve" + type = string +} + +variable "proxmox_password" { + description = "Password for the Proxmox user" + type = string + sensitive = true +} + +variable "proxmox_insecure" { + description = "Skip TLS certificate verification (set true for self-signed certs)" + type = bool + default = true +} From dc4ade7ed1cd27476253d485014c1521c54dbb75 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 Apr 2026 21:31:58 -0500 Subject: [PATCH 2/6] refactor(provider): switch auth from password to API token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer API token over username/password — scoped to least-privilege TerraformRole, reduces blast radius if credentials leak. --- .terraform.lock.hcl | 24 ++++++++++++++++++++++++ CLAUDE.md | 35 +++++++++++++++++++++++++++++++++++ main.tf | 3 +-- terraform.tfvars.example | 5 ++--- variables.tf | 9 ++------- 5 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 .terraform.lock.hcl create mode 100644 CLAUDE.md diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..d584d45 --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,24 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/bpg/proxmox" { + version = "0.101.1" + constraints = "~> 0.73" + hashes = [ + "h1:2MjGiI3uWXkZXOvoLNYq3Mji/cnJCugdzcZAdmYZ4JI=", + "zh:0b2f899c59727b9d5ebc6324944653172e7d4f27fae2670dc10fb717f0dc085a", + "zh:0dfb5f212aef8d5b9372ba89fe08c2404311dc7842d216585f55cae4634e1aa6", + "zh:430c1096c801f615932d8e5ceba5cf1c46fb19c602733b12537292f0379d9875", + "zh:6b2de9a0cfe3939372bb1c4115be81a8f470b2f1f27ff4a47e92bbc1cd16308e", + "zh:6e32494c0e46754946e481473189bd14e9982fb4ab25938d9d8b7125f85ed09b", + "zh:98f847d3b67e551443cb81f96e59cb320f3a5c4bf45ac4a7194eb395f950774d", + "zh:a55dc4a1cdee600a867205cae89c57b36184f63d1fdf16945854ed2a5098012f", + "zh:a80b4777d9cb3c2fd545ecaa0d0f8315363b1a50801638c2866701c50b097710", + "zh:b0512be4d006abcbf91f2a8784ebc11055d3890bc119cf221373b6e820bc9cbb", + "zh:c0207c88fa879aac82a624b10099bfd31b7760ece82fa60fe943e65cc1e7add7", + "zh:c6e722112a1cee87ee621e7dec1cb9a8d2a64ba71d7ae021e1e9456dfb6584d8", + "zh:e0bbca20173fe9051f53b7c211cc5f52552a3c8fe766aca34b7b1880d57a5ec7", + "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", + "zh:f5d7b772797b17fd61d199136e98281b5ca2472732cd97703a28b288cd6eefa4", + ] +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f6f485d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,35 @@ +# Project: ProxmoxInfra + +Terraform infrastructure-as-code for a homelab Proxmox environment. + +## Context + +This repo was started *after* the Proxmox server was already set up manually. +Existing infrastructure was provisioned by hand and must not be touched by +Terraform. Only new resources going forward are managed here. + +## Key rules for this project + +- **Never import or manage existing Proxmox resources** unless the junior + explicitly decides to and understands the risk of state drift. +- **Credentials never go in version control.** `.tfvars` files are gitignored. + Always use `terraform.tfvars.example` as the template pattern. +- **No resources in root module.** As the repo grows, push toward a + `environments/` layout with reusable modules under `modules/`. +- **State is not yet remote.** When a backend is introduced, make it a + deliberate decision with a knowledge transfer on why remote state matters + (locking, team access, DR). + +## Stack + +- Provider: `bpg/proxmox` (not the deprecated Telmate provider) +- Terraform >= 1.0 +- Target: single-node Proxmox VE homelab + +## Learning goals for this project + +- Understand Terraform's core workflow (init / plan / apply / destroy) +- Understand provider authentication and least-privilege API tokens +- Understand state — what it is, why it matters, what happens when it drifts +- Build intuition for when to use a VM vs an LXC container in Proxmox +- Learn to structure a Terraform repo that can scale without becoming a mess diff --git a/main.tf b/main.tf index f990117..4925ac5 100644 --- a/main.tf +++ b/main.tf @@ -11,8 +11,7 @@ terraform { provider "proxmox" { endpoint = var.proxmox_endpoint - username = var.proxmox_username - password = var.proxmox_password + api_token = var.proxmox_api_token # Set to true if using a self-signed certificate (common on home labs) insecure = var.proxmox_insecure diff --git a/terraform.tfvars.example b/terraform.tfvars.example index 57efa2c..36a0c94 100644 --- a/terraform.tfvars.example +++ b/terraform.tfvars.example @@ -2,6 +2,5 @@ # terraform.tfvars is gitignored to keep secrets out of version control. proxmox_endpoint = "https://192.168.1.10:8006/" -proxmox_username = "terraform@pve" -proxmox_password = "changeme" -proxmox_insecure = true +proxmox_api_token = "terraform@pve!terraform-nonprod=" +proxmox_insecure = true \ No newline at end of file diff --git a/variables.tf b/variables.tf index bb857a0..4757e1d 100644 --- a/variables.tf +++ b/variables.tf @@ -3,13 +3,8 @@ variable "proxmox_endpoint" { type = string } -variable "proxmox_username" { - description = "Proxmox user in the form user@realm, e.g. terraform@pve" - type = string -} - -variable "proxmox_password" { - description = "Password for the Proxmox user" +variable "proxmox_api_token" { + description = "Proxmox API token in the form user@realm!token-id=secret, e.g. terraform@pve!api-token-name=" type = string sensitive = true } From 13690e6c603cc29798e033a47e41ff2d34d5bbc5 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 Apr 2026 21:51:21 -0500 Subject: [PATCH 3/6] refactor: restructure repo into environments/modules layout Separates nonprod into its own working directory for independent state isolation. Follows HashiCorp guidance on environment separation. --- .terraform.lock.hcl => environments/nonprod/.terraform.lock.hcl | 0 main.tf => environments/nonprod/main.tf | 0 .../nonprod/terraform.tfvars.example | 0 variables.tf => environments/nonprod/variables.tf | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename .terraform.lock.hcl => environments/nonprod/.terraform.lock.hcl (100%) rename main.tf => environments/nonprod/main.tf (100%) rename terraform.tfvars.example => environments/nonprod/terraform.tfvars.example (100%) rename variables.tf => environments/nonprod/variables.tf (100%) diff --git a/.terraform.lock.hcl b/environments/nonprod/.terraform.lock.hcl similarity index 100% rename from .terraform.lock.hcl rename to environments/nonprod/.terraform.lock.hcl diff --git a/main.tf b/environments/nonprod/main.tf similarity index 100% rename from main.tf rename to environments/nonprod/main.tf diff --git a/terraform.tfvars.example b/environments/nonprod/terraform.tfvars.example similarity index 100% rename from terraform.tfvars.example rename to environments/nonprod/terraform.tfvars.example diff --git a/variables.tf b/environments/nonprod/variables.tf similarity index 100% rename from variables.tf rename to environments/nonprod/variables.tf From 3ccba290b1cd4afe1d8253263a2e7e02c1223790 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 Apr 2026 21:57:58 -0500 Subject: [PATCH 4/6] Hooked nonprod terraform up to nonprod proxmox host --- .gitignore | 1 + environments/nonprod/main.tf | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 146575e..b03bc1e 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ override.tf.json .terraformrc terraform.rc +.claude \ No newline at end of file diff --git a/environments/nonprod/main.tf b/environments/nonprod/main.tf index 4925ac5..11a7255 100644 --- a/environments/nonprod/main.tf +++ b/environments/nonprod/main.tf @@ -10,9 +10,19 @@ terraform { } provider "proxmox" { - endpoint = var.proxmox_endpoint + endpoint = var.proxmox_endpoint api_token = var.proxmox_api_token # Set to true if using a self-signed certificate (common on home labs) insecure = var.proxmox_insecure } + +data "proxmox_virtual_environment_nodes" "vm_nodes" {} + +output "data_proxmox_virtual_environment_nodes" { + value = { + names = data.proxmox_virtual_environment_nodes.vm_nodes.names + cpu_count = data.proxmox_virtual_environment_nodes.vm_nodes.cpu_count + online = data.proxmox_virtual_environment_nodes.vm_nodes.online + } +} From ef777e63739cecf480d7c346d5e3092c6b2dc16e Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 Apr 2026 22:00:05 -0500 Subject: [PATCH 5/6] remove CLAUDE.md --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b03bc1e..212fb4d 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,6 @@ override.tf.json .terraformrc terraform.rc -.claude \ No newline at end of file +# Claude specific ingores +.claude +CLAUDE.md \ No newline at end of file From 27e45bb2575d19620f722592da7b616f9f4b243c Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 Apr 2026 22:02:11 -0500 Subject: [PATCH 6/6] remove CLAUDE.md from cache as well --- CLAUDE.md | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index f6f485d..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,35 +0,0 @@ -# Project: ProxmoxInfra - -Terraform infrastructure-as-code for a homelab Proxmox environment. - -## Context - -This repo was started *after* the Proxmox server was already set up manually. -Existing infrastructure was provisioned by hand and must not be touched by -Terraform. Only new resources going forward are managed here. - -## Key rules for this project - -- **Never import or manage existing Proxmox resources** unless the junior - explicitly decides to and understands the risk of state drift. -- **Credentials never go in version control.** `.tfvars` files are gitignored. - Always use `terraform.tfvars.example` as the template pattern. -- **No resources in root module.** As the repo grows, push toward a - `environments/` layout with reusable modules under `modules/`. -- **State is not yet remote.** When a backend is introduced, make it a - deliberate decision with a knowledge transfer on why remote state matters - (locking, team access, DR). - -## Stack - -- Provider: `bpg/proxmox` (not the deprecated Telmate provider) -- Terraform >= 1.0 -- Target: single-node Proxmox VE homelab - -## Learning goals for this project - -- Understand Terraform's core workflow (init / plan / apply / destroy) -- Understand provider authentication and least-privilege API tokens -- Understand state — what it is, why it matters, what happens when it drifts -- Build intuition for when to use a VM vs an LXC container in Proxmox -- Learn to structure a Terraform repo that can scale without becoming a mess