Automating Ubuntu VM Deployment on Proxmox VE with Terraform + Cloud-Init

Md RaselMd Rasel
3 min read

In modern infrastructure management, repeatability and automation are key. Manually creating VMs through a GUI works for quick tests, but it doesn’t scale, and it’s error-prone.

In this post, I’ll share how I automated the creation of multiple Ubuntu 22.04 VMs on Proxmox VE 8.4 using Terraform and cloud-init — complete with static IP addresses, and configured for password authentication without SSH keys.

🛠 Why Terraform with Proxmox?

Terraform lets you define infrastructure as code (IaC).

  • You can version control your setup

  • Spin up or destroy VMs in seconds

  • Enforce consistency across environments

Proxmox has an API, and the Telmate Terraform provider makes it possible to drive VM creation directly from your .tf files.

🗂 Folder Structure
.

├── main.tf # The VM resource definitions

├── variables.tf # All configuration variables

├── versions.tf # Terraform & provider versions

├── terraform.tfvars # My actual values for variables

🔧 What I Built

I created a Terraform configuration that:

  • Connects to Proxmox via API token authentication

  • Clones a cloud-init–enabled Ubuntu 22.04 template

  • Deploys three VMs with:

    • Static IP addresses

    • Cloud-init user accounts

    • Password authentication instead of SSH keys

  • Outputs VM names and IDs automatically after provisioning

Pre-requisite:

  • Proxmox VE-8.4 installed

  • Terraform installed on Local machine

  • Properly configured Network on Proxmox

Task List for automation:

  • Ubuntu VM template ready from Proxmox CLI

  • Proxmox User creation and api token configuration

  • Writing the terraform artifact

Ubuntu VM template ready from Proxmox CLI

#Run on the Proxmox node (adjust storage if not local-lvm):

# 1) Get Ubuntu 22.04 cloud image
cd /var/lib/vz/template/iso wget -O jammy.img https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img

# 2) Create a VM shell (ID 9000) for the template
qm create 9000 --name ubuntu-22.04-ci-template --memory 2048 --cores 2 \
  --net0 virtio,bridge=vmbr0

# 3) Import the cloud image as a disk on your storage (edit storage if needed)
qm importdisk 9000 /var/lib/vz/template/iso/jammy.img local-lvm

# 4) Attach disk + cloud-init, set boot order
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
qm set 9000 --ide2 local-lvm:cloudinit
qm set 9000 --boot c --bootdisk scsi0
qm set 9000 --serial0 socket --vga serial0

# (optional) grow disk to match your TF var (e.g., 25G)
qm resize 9000 scsi0 25G

# 5) Enable QEMU guest agent (useful for IP reporting)
qm set 9000 --agent enabled=1

# 6) Convert to template
qm template 9000

Proxmox User creation and api token configuration

In the Proxmox web UI:

  • Go to Datacenter → Permissions → Users → Add.

  • User ID: terraform

  • Realm: pve (or pam if you want system authentication)

  • Password: (set any; not used for token auth)

  • Click Add.

💡
Or you can Create user and api token from CLI also
# 1) make sure the user exists in pve realm

pveum user add terraform@pve || true

# 2) (optional) give the user a password you’ll remember

pveum passwd terraform@pve

# 3) create a new API token WITH privilege separation

pveum user token add terraform@pve tf --privsep 1

# -> copy the returned "value" (token secret). Keep it safe.

Check Your API and user from Postman

curl -k -H "Authorization: PVEAPIToken=terraform@pve!tf=your api token" \
  https://192.168.31.43:8006/api2/json/access/users
💡
Now write the terraform code and run with below command. You can find the terraform code on below GitHub account.

Github Link for Terraform Code

rm -rf .terraform .terraform.lock.hcl # If previous step was hold
terraform init -upgrade
terraform plan
terraform apply

0
Subscribe to my newsletter

Read articles from Md Rasel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Md Rasel
Md Rasel

I’m Md. Rasel, a DevOps Lead at Synesis IT PLC with over a decade of experience in DevOps, Cloud Infrastructure, and Virtualization. My work blends automation, scalability, and reliability to help organizations build resilient, high-performing systems. I specialize in Kubernetes, Docker, Terraform, Jenkins, AWS, OCI, and Proxmox VE, along with CI/CD pipeline design, cloud-native application deployment, and infrastructure automation. My experience spans managing multi-tier applications, orchestrating containerized workloads, implementing secure DevSecOps practices, and optimizing cloud resources for cost and performance. Beyond hands-on engineering, I’m passionate about mentoring and training, having conducted technical workshops on topics like Kubernetes, network automation, monitoring, and cloud strategies at universities and industry events. When I’m not solving infrastructure challenges, I share insights on DevOps best practices, automation strategies, cloud-native technologies, and real-world troubleshooting—making complex tech approachable and actionable. Specialties: CI/CD Pipelines (Jenkins, GitLab CI) Kubernetes & Container Orchestration Infrastructure as Code (Terraform, Ansible) Cloud Platforms (AWS, Oracle Cloud, Azure) Monitoring & Observability (Prometheus, Grafana, ELK, Zabbix) DevSecOps & Security Automation 💡 Let’s connect—I’m always open to discussions about scalable architectures, DevOps automation, and cloud-native innovations.