Provisioning Proxmox VMs with Terraform: Complete Guide
Learn how to use the Telmate Terraform provider for Proxmox VE to define, plan, and deploy virtual machines as code with API tokens, variables, and state management.
Terraform lets you define your Proxmox infrastructure as code — repeatable, version-controlled, and auditable. Instead of clicking through the web UI to create VMs, you write declarative configuration files and let Terraform handle the API calls. This guide walks through setting up the Telmate Proxmox provider, configuring API authentication, and deploying your first VM.
Prerequisites
You need Terraform installed on your workstation and a Proxmox VE node with API access. You should also have a VM template ready (a cloud-init enabled template works best with Terraform).
Setting Up a Proxmox API Token
Create a dedicated API token for Terraform rather than using your root credentials:
# On the Proxmox node, create a user for Terraform
pveum user add terraform@pve --comment "Terraform automation"
# Create a role with the necessary permissions
pveum role add TerraformRole -privs "VM.Allocate VM.Clone VM.Config.CDROM VM.Config.CPU VM.Config.Cloudinit VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Migrate VM.Monitor VM.PowerMgmt Datastore.AllocateSpace Datastore.Audit Pool.Allocate Sys.Audit Sys.Console Sys.Modify SDN.Use"
# Assign the role to the user
pveum aclmod / -user terraform@pve -role TerraformRole
# Create an API token (save the output — the secret is shown only once)
pveum user token add terraform@pve terraform-token --privsep=0
The --privsep=0 flag gives the token the same permissions as the user. Store the token ID and secret securely.
Terraform Provider Configuration
Create a project directory and configure the Proxmox provider:
# versions.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
proxmox = {
source = "Telmate/proxmox"
version = "~> 3.0"
}
}
}
# provider.tf
provider "proxmox" {
pm_api_url = var.proxmox_api_url
pm_api_token_id = var.proxmox_api_token_id
pm_api_token_secret = var.proxmox_api_token_secret
pm_tls_insecure = true # Set to false if using valid SSL certs
}
Defining Variables
Keep sensitive values out of your configuration files using variables:
# variables.tf
variable "proxmox_api_url" {
description = "Proxmox API URL"
type = string
default = "https://192.168.1.100:8006/api2/json"
}
variable "proxmox_api_token_id" {
description = "Proxmox API token ID"
type = string
sensitive = true
}
variable "proxmox_api_token_secret" {
description = "Proxmox API token secret"
type = string
sensitive = true
}
variable "vm_count" {
description = "Number of VMs to create"
type = number
default = 3
}
Create a terraform.tfvars file (add it to .gitignore) with your actual credentials:
# terraform.tfvars
proxmox_api_token_id = "terraform@pve!terraform-token"
proxmox_api_token_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Defining a VM Resource
Here is a complete VM resource definition that clones from a template and uses cloud-init for guest configuration:
# main.tf
resource "proxmox_vm_qemu" "web_server" {
count = var.vm_count
name = "web-${count.index + 1}"
target_node = "pve"
clone = "ubuntu-template"
agent = 1
os_type = "cloud-init"
cores = 2
sockets = 1
memory = 2048
scsihw = "virtio-scsi-single"
bootdisk = "scsi0"
disks {
scsi {
scsi0 {
disk {
size = "20G"
storage = "local-lvm"
}
}
}
}
network {
model = "virtio"
bridge = "vmbr0"
}
# Cloud-init settings
ipconfig0 = "ip=192.168.1.${110 + count.index}/24,gw=192.168.1.1"
nameserver = "8.8.8.8"
ciuser = "admin"
sshkeys = file("~/.ssh/id_rsa.pub")
lifecycle {
ignore_changes = [
network,
]
}
}
Plan, Apply, and Manage State
Initialize the project and deploy:
# Initialize Terraform and download the provider
terraform init
# Preview what will be created
terraform plan
# Apply the configuration (creates the VMs)
terraform apply
# View current state
terraform state list
# Show details of a specific resource
terraform state show proxmox_vm_qemu.web_server[0]
# Destroy all managed resources
terraform destroy
State Management Best Practices
The Terraform state file contains your infrastructure mapping. For team environments, use a remote backend:
# Add to versions.tf for S3-compatible backend
terraform {
backend "s3" {
bucket = "terraform-state"
key = "proxmox/terraform.tfstate"
endpoint = "https://minio.local:9000"
region = "us-east-1"
skip_credentials_validation = true
skip_metadata_api_check = true
force_path_style = true
}
}
Practical Tips
- Always run
terraform planbeforeapply— review what will change - Use
countorfor_eachfor multiple similar VMs to avoid code duplication - Pin the provider version to avoid unexpected breaking changes
- Never commit
terraform.tfvarsor state files to version control - Monitor your deployed VMs with ProxmoxR to track resource utilization after provisioning
Terraform with the Proxmox provider transforms VM management from a manual process into a repeatable workflow. Combined with cloud-init templates, you can spin up fully configured environments in minutes.
Take Proxmox management mobile
All the features discussed in this guide — accessible from your phone with ProxmoxR. Real-time monitoring, power control, firewall management, and more.