Platform & Orchestration

Terraform

Infrastructure from declared state, built through the bpg/proxmox provider pinned to version 0.111.1 - one workspace per VM so a mistake blasts one machine, not the fleet, and a pipeline that rolls forward cleanly when a step fails.

What it is and whyHow I use it inArchitectureLessons learned and gotchasImpactFurther reading

What it is & why I use it

Terraform is how VMs come into existence in AutomationLab. The hypervisor is driven entirely through the bpg/proxmox provider - there is no hand-built guest anywhere in the lab. Terraform owns the "make the machine exist and match what the code says" half of provisioning; configuration management takes it from there.

I use it because infrastructure should be declarative and diffable. A plan shows exactly what will change before anything does, and drift surfaces as a diff instead of a surprise - which is the whole reason to treat infrastructure as code rather than as a sequence of console clicks.

How I use it in the lab

  • One workspace per VM. Each machine has its own workspace and state rather than one giant shared state for the whole lab. A bad apply can only touch the one VM it owns.
  • Driven by the pipeline. Terraform runs as the provision stage of the Jenkins flow, after IP allocation and before configuration - plan, gated apply, then hand off.
  • Roll-forward on partial failure. If a later stage fails, the pipeline cleans up forward to a consistent state rather than leaving a half-built VM lying around, and a decommission path reverses what was created.
  • Pinned provider and tool versions. The provider and the Terraform binary are pinned to explicit versions so a run is reproducible and does not silently change behavior when an upstream release lands.

Architecture

Terraform architecture: One VM, one workspace NetBox reserves an address, Terraform plans and applies one isolated VM workspace, and Ansible receives the finished guest for configuration. ARCHITECTURE FLOW ONE VM, ONE WORKSPACE Address reserved: NetBox records one allocation ADDRESS RESERVED NetBox records one allocation VM workspace: State is isolated to one machine VM WORKSPACE State is isolated to one machine Terraform plan: The proposed change is visible TERRAFORM PLAN The proposed change is visible Operator gate: The plan is reviewed before apply OPERATOR GATE The plan is reviewed before apply Provider apply: Proxmox receives the approved change PROVIDER APPLY Proxmox receives the approved change Configuration handoff: Ansible configures the guest CONFIGURATION HANDOFF Ansible configures the guest Cyan. Automated step or path. Amber. Operator or policy gate. Green. Recorded or healthy outcome. Dashed box. Stored state or record. Rounded box. Actor or process. Arrow. Direction of work or data.
Each VM keeps its own state from address allocation through plan, approval, apply, and configuration handoff. The diagram omits addresses and hostnames.

Lessons learned & gotchas

Gotcha - a version in the listing is not a downloadable artifact When pinning a tool version, "the version appears in the releases directory" is not the same as "the release exists." A version can be listed while the specific artifact you need returns a 404. So I verify that the actual artifact URL returns 200 before pinning to it. Skip that and a pipeline that passed yesterday breaks on a fresh agent that has to download the pinned binary for the first time.
  • Per-VM state is worth the extra files. One monolithic state for everything is tidy until a single bad apply or a lock left behind takes the whole lab's provisioning hostage. Small, isolated states keep the blast radius to one machine.
  • The plan is the review, so gate the apply. Applying straight from a push defeats the point of a plan. An approval-gated apply in the pipeline means the diff is actually looked at before infrastructure moves.
  • Roll-forward beats leaving wreckage. A failed provision that cleans up to a known state is recoverable; a half-built VM with orphaned state is a manual mess. Write the failure path explicitly.

Impact

1 VM
per workspace / state
100%
guests from code
200
verified before pinning

Terraform is what makes the lab reproducible from the metal up: every VM is described in code, isolated in its own state, and created through a gated, roll-forward pipeline. The version-pinning lesson is a small one that saves a whole class of "worked yesterday, broken today" failures - proof that in IaC the boring details are exactly where reliability lives.

Further reading