Skip to main content
  1. Posts/

Homelab: Proxmox VMs with Terraform

Homelab: Proxmox, Talos, and Flux - This article is part of a series.
Part 1: This Article

I started my homelab clicking around the Proxmox web interface. Create a VM, set the CPU, disk, memory, boot it, configure it. It worked fine for one or two nodes. After a while I realized I was doing the exact same steps over and over, and there’s no way I’m remembering all these settings if I ever need to rebuild.

That’s when I switched to Terraform. Now everything is code. I have control plane nodes running Talos, worker nodes running Talos, and a couple AlmaLinux VMs for monitoring and other utility work. All of it gets created the same way every time. When something breaks, I blow it away and recreate it from code.

This post covers how I set that up.

Why this matters for homelabbing
#

The Proxmox UI is fine for clicking around once. But manually creating five VMs with identical specs is tedious and error-prone. You forget the exact RAM size, or the CPU count is different on one node, or you use a different disk size by accident.

Terraform eliminates that. Define it once in code, create it the same way every time. You can destroy your entire cluster with one command and recreate it in a few minutes. That’s powerful for learning.

Plus it’s in Git, so you have version history if you need to go back.

Getting the API token set up
#

Proxmox has an API, and Terraform uses it. First step is giving Terraform the permissions to actually do things.

Log into Proxmox and run these commands (or do this through the web UI if you prefer):

pveum role add TerraformProv -privs "Datastore.AllocateSpace Datastore.Audit Pool.Allocate Sys.Audit Sys.Console Sys.Modify VM.Allocate VM.Audit VM.Clone VM.Config.CDROM VM.Config.Cloudinit VM.Config.CPU VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Migrate VM.Monitor VM.PowerMgmt SDN.Use"

pveum user add terraform-prov@pve --password <password>

pveum aclmod / -user terraform-prov@pve -role TerraformProv

pveum user token add terraform-prov@pve tftoken

That creates a user specifically for Terraform, gives it only the permissions it needs, and generates an API token. Save the token ID and secret. You’ll put those in your terraform config.

Structure
#

My setup uses modules. I have one module that creates Talos VMs, another that creates AlmaLinux LXCs. Each module knows how to set CPU, memory, disk, and networking for its node type.

The main main.tf calls these modules for each node I want. So creating five Talos nodes is just calling the module five times with different names.

Example terraform.tfvars:

proxmox_node           = "pve01"
proxmox_api_url        = "https://your-proxmox-server:8006/api2/json"
proxmox_api_token_id   = "terraform-prov@pve!tftoken"
proxmox_api_token_secret = "xxxxxxxxxxxx"

Then:

terraform init
terraform plan
terraform apply

Terraform creates all your VMs, configures their cloud-init, sets up the network. Everything happens automatically.

The lesson I learned
#

The first time I did this, I just went for it without planning. I learned the hard way that Terraform isn’t great at managing partial failures. If something goes wrong halfway through creating five nodes, you either have to manually clean up or use terraform destroy and start over.

Now I test the whole thing with terraform plan first, make sure it looks right, then apply. And I have the destroy commands memorized.

Next#

Once your VMs are up and working, they’re still just blank operating systems. Part 2 covers turning them into a Kubernetes cluster using Talos Linux.

Homelab: Proxmox, Talos, and Flux - This article is part of a series.
Part 1: This Article