Proxmox VM templates with cloud-init
March 15, 2025Proxmox VM templates are preconfigured VM images that you can clone and launch other VMs from. Here are the steps to prepare an Ubuntu 24.04 VM template.
We assume you want a template with these options in the following instructions:
- 9000 (Proxmox vmid)
- noble-server-cloudimg-amd64.img (Ubuntu cloud image)
- local-lvm (Proxmox storage)
Set up VM template
- Download this image through the UI:
https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
- Create a VM with no media and disk, set default CPU, memory and storage options for your VM clones
- Import the Ubuntu cloud image as a disk and specify a format
qm disk import 9000 /var/lib/vz/template/iso/noble-server-cloudimg-amd64.img local-lvm --format qcow2.
- The qcow2 format supports snapshots
- Note that if you’re using a
LVM-Thin
storage only theraw
format is supported (which is the default format), so you can omit the--format
parameter. It supports snapshots this way as well.
- This disk shows up in the VM hardware tab as
Unused Disk 0
, double click it and add it- Enable the
Discard
andSSD emulation
parameters
- Enable the
- Change the boot order, enable
scsi0
and disable the other options - Create the template with
qm template 9000
- Add sensible defaults like SSH keys and DNS servers to the cloud-init tab in the UI
- To check what the auto generated user cloud-init is
qm cloudinit dump 9000 user
- To check what the auto generated user cloud-init is
Adding a vendor file to cloud-init
The default cloud-init generated by Proxmox has very limited options, so let’s add some additional options via cloud-init’s vendor data. Feel free to add more cloud-init options if you want to, but you most probably just want the ability to add more packages and run some bash commands.
mkdir -p /var/lib/vz/snippets
cat > /var/lib/vz/snippets/vendor.yaml << 'EOF'
#cloud-config
timezone: "Asia/Kuala_Lumpur"
package_update: true
package_upgrade: true
package_reboot_if_required: true
packages:
- curl
- git
- python3-venv
- qemu-guest-agent
- unzip
runcmd:
# install Docker
- curl -fsSL https://get.docker.com -o get-docker.sh
- sh get-docker.sh
- rm get-docker.sh
- groupadd docker
- usermod -aG docker ubuntu
- systemctl start qemu-guest-agent
EOF
qm set 9000 --cicustom "vendor=local:snippets/vendor.yaml"
Use
- Right click this template VM and clone it in the UI (recommended to do a full clone)
- Edit the options before you start it
- In the Hardware tab, resize the
scsi0
disk to the size you require - In the Cloud-Init tab, edit the password and SSH public key (user will default to
ubuntu
)- If you don’t give it a password, you won’t be able to login through the VM terminal in the Proxmox UI, but you can still SSH to it if you’ve added a public key
- just give it a password like
admin123
, especially if you’re sharing Proxmox with other people, then change it in the VM
- In the Hardware tab, resize the
- Since qemu-guest-agent is already installed, you should see the IP pop up in the Proxmox UI when it’s ready
- Edit the options before you start it
Notes
- Big raw image disks actually take a while to clone, it’s better to start with a small disk, then resize the main VM disk when the VM clone is created, cloud-init will automatically resize it with
growpart
andresizefs
- This doesn’t seem to introduce any additional wear on the SSD though
- When adding the user to the docker group, the user is hardcoded as
ubuntu
. Would be nicer to programmatically grab it from the Proxmox managed cloud-init as well.- If you create a user with a different name, you have to add it to the docker group again yourself
- The Proxmox generated DNS nameserver settings don’t seem to work at all at the moment too
References
- https://homelab.casaursus.net/cloud-init/
- https://www.youtube.com/watch?v=shiIi38cJe4
- https://forum.proxmox.com/threads/combining-custom-cloud-init-with-auto-generated.59008/page-3
- https://pve.proxmox.com/wiki/Cloud-Init_Support
- https://forum.proxmox.com/threads/ubuntu-cloud-init-setting-dns-not-working.111574/