Automate Proxmox VM Creation With Cloud-Init

This post provides step by step instructions for you to automate proxmox VM creation with cloud-init.

This post gives you step-by-step instructions of how to automate proxmox VM creation. I’ll use ubuntu as an example.


The overall strategy is to use the ubuntu cloud image to create a Proxmox VM template, and attach a cloud-init disk to it. After that, we can clone the template to create new VM, and new VM will automatically bootstrap itself, e.g., changing the hostname.

Prepare tools

Install virt-customize

apt-get install libguestfs-tools

Prepare The Ubuntu Cloud Image

Use the following commands to prepare the ubuntu cloud image:

# Create a new directory for our image building.
mkdir ubuntu-cloud-image
cd ubuntu-cloud-image

# Download the cloud image.

# Resize the image to 16GB. Feel free to change it to your desired size.
qemu-img resize noble-server-cloudimg-amd64.img 16G

# Install avahi-deamon for mdns.
virt-customize -a noble-server-cloudimg-amd64.img --run-command 'apt update && apt install avahi-daemon -y && cloud-init clean --logs --machine-id --configs all --reboot && sudo truncate -s 0 /etc/machine-id /var/lib/dbus/machine-id'

Prepare The Proxmox VM Template

Then, we prepare the Proxmox VM template with the following steps.

Create A Temporary VM

# Create a VM with the following configuration:
# * vmid: 1000 (feel free to change this)
# * memory: 4GB
# * network: attached to bridge vmbr0
qm create 1000 --name ubuntu-noble-template --memory 4096 --net0 virtio,bridge=vmbr0

Attach The Ubuntu Cloud Image

# Attach the ubuntu cloud image onto the VM.
# Note that here ssd is my storage name. You'll need to replace it with yours.
qm importdisk 1000 noble-server-cloudimg-amd64.img ssd

# Make the attached disk scsi0.
qm set 1000 --scsihw virtio-scsi-pci --scsi0 ssd:vm-1000-disk-0

# Set scsi0 as the first boot device.
qm set 1000 --boot c --bootdisk scsi0

Create A Cloud-init Drive

# Create a cloud-init drive.
qm set 1000 --ide2 ssd:cloudinit

# Configure your cloud-init drive. Replace the username, password and sshkeys for your case.
qm set 1000 --ciuser swe --cipassword swe-passwd --sshkeys ~/.ssh/ --ipconfig0 ip=dhcp

Convert The VM Into A Template

# Convert the VM into a template.
qm template 1000

Create VM

# Create a VM using the template, and set the name to ubuntu-vm1.
qm clone 1000 1101 --full --name ubuntu-vm1

# Create another VM using the template, and set the name to ubuntu-vm2.
qm clone 1000 1102 --full --name ubuntu-vm2

To access these VMs, you can do

# Use the following command to access ubuntu-vm1 if you have mdns included in your template, and you are within the same LAN as ubuntu-vm1.
ssh swe@ubuntu-vm1.local

# Use the following command to access ubuntu-vm2 if you have mdns included in your template, and you are within the same LAN as ubuntu-vm2.
ssh swe@ubuntu-vm2.local