Speed up Proxmox VM deployment with Packer

Discovering Packer
In my journey to automate infrastructure, I stumbled upon Packer, a fascinating tool developed by HashiCorp. It's a free tool that has allowed me to create prebuilt images for various platforms like AWS, Azure, Digital Ocean, VirtualBox, Proxmox, and many other cloud providers or hypervisors.
What I love most about this command-line tool is that it lets me create custom images with:
- My favorite applications pre-installed
- User accounts ready to go
- SSH keys configured
- Network settings all set up
- And tons of other customizations...
I was blown away by how powerful it is for automating infrastructure deployment. Thanks to Packer, I can spin up my testing or development environments in no time. The coolest part? It works on every system: Windows, macOS, and Linux!
How I Got Packer Working with Proxmox
While exploring Packer, I found out it offers two different ways to work with Proxmox:
proxmox-iso
proxmox-clone

Source: Official Packer Docs
For this guide, I chose to use proxmox-iso
because it works perfectly with Proxmox VM templates.
My First Template: A Step-by-Step Experience
What I Wanted to Create
I set out to create a template based on Ubuntu 24.04 (Noble) with these specs:
- CPU: 2 cores (perfect for my testing needs)
- RAM: 2048 MB (2GB)
- Disk: 20GB (plenty to start with)
- OS: Ubuntu 24.04
Setting Up Packer
Installation
The first cool thing about Packer is that it doesn't need to be on the same machine as Proxmox. To install it, I followed the official documentation.
On my Linux machine, I used these commands:
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install packer
File Organization
To save you some time, I've created a repository you can clone:
git clone https://github.com/LudovicARHIMAN/Packer-Templates.git
Here's how I organized the files:
.
├── README.md
├── credentials.pkr.hcl
└── ubuntu-server-noble
├── files
│ └── 99-pve.cfg
├── http
│ ├── meta-data
│ └── user-data
└── ubuntu-server-noble.pkr.hcl
You won't find thecredentials.pkr.hcl
file in the repo as it contains sensitive information. I excluded it with.gitignore
for security reasons.
Create your own credentials.pkr.hcl
file with this template:
proxmox_api_url = "https://0.0.0.0:8006/api2/json" # Your Proxmox address
proxmox_api_token_id = "GENERATED_API_TOKEN-ID" # Your token ID
proxmox_api_token_secret = "GENERATED_API_Secret"
Setting Up the API Token in Proxmox
To let Packer talk to Proxmox, we need to create an API token. Here's how I did it:
- In the Proxmox web interface, I went to Datacenter > Permissions > API Token
- Clicked on Add to create a new token

Then, I updated my credentials.pkr.hcl
file with my information:
proxmox_api_url = "https://pve.reverse9.xyz:8006/api2/json" # My Proxmox server
proxmox_api_token_id = "root@pam!packer" # My token ID
proxmox_api_token_secret = "my-secret-token-here"
Understanding the Configuration Files
The Main Template File
The file ubuntu-server-noble/ubuntu-server-noble.pkr.hcl
is where the magic happens. Let me walk you through how I configured it:
1. The Essential Variables
variable "proxmox_api_url" {
type = string
}
variable "proxmox_api_token_id" {
type = string
}
variable "proxmox_api_token_secret" {
type = string
sensitive = true
}
These variables are crucial for connecting to Proxmox.
2. VM Configuration
I split the configuration into several parts to keep things clear:
a. Proxmox Connection
proxmox_url = "${var.proxmox_api_url}"
username = "${var.proxmox_api_token_id}"
token = "${var.proxmox_api_token_secret}"
b. Basic Settings
node = "pve"
vm_id = "500"
vm_name = "ubuntu-server-noble"
template_description = "My Ubuntu Server Noble Image"
c. OS Settings
iso_url = "https://releases.ubuntu.com/noble/ubuntu-24.04.2-live-server-amd64.iso"
iso_checksum = "d6dab0c3a657988501b4bd76f1297c053df710e06e0c3aece60dead24f270b4d"
iso_storage_pool = "ISO"
d. Hardware Resources
qemu_agent = true
scsi_controller = "virtio-scsi-pci"
disks {
disk_size = "20G"
format = "raw"
storage_pool = "local"
type = "virtio"
}
cores = "2"
memory = "2048"
e. Network Setup
network_adapters {
model = "virtio"
bridge = "vmbr0"
firewall = "false"
}
Cloud-init Configuration
In the user-data
file, I set up the automatic installation:
autoinstall:
version: 1
locale: en_US
keyboard:
layout: fr
ssh:
install-server: true
allow-pw: true
disable_root: true
ssh_quiet_keygen: true
allow_public_ssh_keys: true
packages:
- qemu-guest-agent
- sudo
storage:
layout:
name: direct
swap:
size: 0
user-data:
package_upgrade: false
timezone: Indian/Reunion
users:
- name: admin
groups: [adm, sudo]
lock-passwd: false
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK/b1GlV0l/Os3je6ZWRFvhmyMh/2JJ1PyrbZJAP89DL ubuntu-pkr
Creating the Template: The Moment of Truth!
Checking the Configuration
Before launching the creation, I made sure everything was properly configured:
cd ubuntu-server-noble/
packer validate -var-file='../credentials.pkr.hcl' ./ubuntu-server-noble.pkr.hcl
If you see "The configuration is valid", you're good to go!
Starting the Build
I kicked off the build with this command:
packer build -var-file='../credentials.pkr.hcl' ./ubuntu-server-noble.pkr.hcl
This command will:
- Download the Ubuntu ISO
- Upload it to my Proxmox server
- Start up a new VM
- Configure it automatically through SSH
- Turn it into a template
The Result
And here's what I got:
My template showing up nicely in Proxmox

With exactly the specifications I wanted

Now I can create as many VMs as I want from this template, all configured exactly the way I need them. That's the power of automation!