Setting up Cloud Init Ubuntu Image on Proxmox

Oct 15, 2022·
Derek Armstrong - Software Engineer · AI · Infrastructure
Derek Armstrong
· 3 min read

This post shows a compact, repeatable flow for creating a Cloud-Init based Ubuntu template in Proxmox so you can spin up configured VMs quickly.

Quick run: download an Ubuntu cloud image, import it into Proxmox, add a Cloud-Init drive, set boot order, convert to a template, then clone.

You will need:

  • A Proxmox VE host with LVM (or other writable storage like local-lvm)
  • SSH or shell access to your Proxmox host
  • A public SSH key (for injecting into cloud-init)

Quick checklist

  • Download cloud image
  • Create a small VM (temporary)
  • Import disk, attach to VM
  • Add cloud-init drive and configure user/ssh
  • Convert VM to template
  • Clone when needed

Step-by-step

1) Download the Ubuntu cloud image

Choose the release you prefer and download the cloud image. Example (Focal):

wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img

2) Create a temporary VM to attach the image to

Adjust memory and CPU to taste — this VM will become the template.

qm create 8000 --memory 2048 --core 2 --name ubuntu-cloud --net0 virtio,bridge=vmbr0

3) Import the cloud image into storage

Import the downloaded image into a Proxmox storage pool (example uses local-lvm):

qm importdisk 8000 focal-server-cloudimg-amd64.img local-lvm
qm set 8000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-8000-disk-0

5) Add the Cloud-Init drive

qm set 8000 --ide2 local-lvm:cloudinit

6) Make the VM boot from the disk

qm set 8000 --boot c --bootdisk scsi0

7) Add a serial console (optional, helpful for headless debugging)

qm set 8000 --serial0 socket --vga serial0
Don’t Start Yet

Warning — do not start the VM yet. Configure cloud-init and hardware first. Starting too early can record IDs/state you may not want in your template.

8) Configure Cloud-Init fields (hostname, user, SSH key)

You can set these with the GUI or via qm set. Example CLI:

qm set 8000 --ciuser ubuntu --sshkey "$(cat ~/.ssh/id_rsa.pub)"
qm set 8000 --citype nocloud

If you want to provide a full user-data/meta-data payload for NoCloud, you can supply files or use Proxmox GUI fields.

9) Convert the VM to a template

qm template 8000

10) Clone the template whenever you need a new VM

qm clone 8000 135 --name yoshi

Tips

  • Resize disks after cloning if you need per-VM different sizes; keep the template small.
  • Put idempotent provisioning (Ansible, cloud-init modules) in the guest rather than baking many steps into the template.

Troubleshooting

If you accidentally booted a template (or need a fresh machine-id inside a guest):

sudo rm -f /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id

Shutdown the VM and do not boot it; a new id will be generated on next boot. If it’s not generated automatically, run:

sudo systemd-machine-id-setup

If cloud-init doesn’t apply after cloning, verify the cloud-init datasource type and that Proxmox’s cloud-init fields are populated correctly for the new host.


What I Learned

  • Cloud-init templates save hours per VM when you deploy regularly
  • Never start a VM before configuring cloud-init — booting early bakes state into the template
  • Keep the template minimal; use idempotent provisioning (Ansible, cloud-init modules) for post-clone customization
  • Always use SCSI for the imported disk for performance
  • Reset machine-id after cloning if cloud-init doesn’t apply correctly

Next

Derek Armstrong - Software Engineer · AI · Infrastructure
Authors
Software Engineer · AI · Infrastructure
I’m Derek — software engineer, infrastructure nerd, and chronic tinkerer. 10+ years building payment platforms, production systems, and the kind of infrastructure that has to work at 3am whether I’m awake or not. When I’m not at my day job, I’m running local LLMs on dual 3090s, 3D printing things my wife didn’t ask for, and writing about all of it here. Topics range from code to infrastructure, AI, and whatever I broke this week.