Proxmox Cloud-Init Templates: New VMs in 30 Seconds Flat

Turn an Ubuntu cloud image into a Proxmox template and clone ready-to-boot VMs in seconds — user, SSH key, and IP pre-configured by cloud-init, no installer wizard ever again.

On this page
  1. How the template pipeline works
  2. Task 1: Download the Ubuntu cloud image
  3. Task 2: Build the VM shell
  4. Task 3: Convert it to a template
  5. Task 4: Clone and personalize
  6. When to use this (and when not to)

You’ve created a VM the traditional way: upload an ISO, click through the wizard, answer the installer’s questions, wait for packages to copy, install the guest agent. Twenty minutes, easy. Now imagine needing five more VMs this month — a test box, a Docker host, something to break on purpose. Nobody wants to sit through that installer five more times.

This is the problem cloud-init templates solve. You build one golden master from a pre-installed cloud image, and from then on every new VM is a 30-second clone that boots already configured — your user, your SSH key, its own IP — no installer, no wizard, no console typing.


How the template pipeline works

Cloud-init is a small service baked into the “cloud image” builds of most Linux distributions. On a VM’s very first boot it looks for configuration — Proxmox hands it over on a tiny virtual CD-ROM called the cloud-init drive — and applies it: creates your user, installs your SSH key, configures the network. Then it gets out of the way forever.

One template, endless clonesCloud image.img · pre-installed OSimportTemplate 9000read-only masterLOCKED — never bootsclone · ~30 s eachweb0110.0.0.41 · your key · booteddocker0110.0.0.42 · your key · bootedtest0110.0.0.43 · your key · bootedcloud-init drive (virtual CD-ROM)user · password · SSH key · IP configread once on first boot, then ignored forever

The pipeline has three stages: download a cloud image, wrap it in a VM shell and convert that to a template (a read-only master Proxmox will never boot), then clone the template whenever you need a fresh VM. The clone reads its personal settings from the cloud-init drive on first boot and comes up ready for SSH.

Warning

First: make these values your own. The commands below use placeholders — swap them before running: local-lvm (your VM disk storage; check your storage setup), local (your ISO/snippet storage), 9000 (template VMID), 10.0.0.41/24 and 10.0.0.1 (example IP and gateway on a dummy 10.0.0.x network — use your own subnet), ubuntu (the username you want), and the path to your SSH public key.


Task 1: Download the Ubuntu cloud image

1Grab the image on the Proxmox host2 min

SSH into your Proxmox node and download Ubuntu’s current LTS cloud image. Note it’s an .img, not an .iso — there is no installer inside, just a finished OS.

On the Proxmox host

wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img \
-O /var/lib/vz/template/iso/noble-server-cloudimg-amd64.img

Debian, Fedora, Rocky, and openSUSE all publish equivalent cloud images — the rest of this guide works the same with any of them.


Task 2: Build the VM shell

1Create an empty VM2 min

This creates the virtual hardware only — no disk yet. The flags mirror the wizard fields from the VM walkthrough, with one addition: a serial console, which cloud images expect.

Create the shell

qm create 9000 \
--name ubuntu-2404-template \
--machine q35 --bios ovmf --efidisk0 local-lvm:0,efitype=4m,pre-enrolled-keys=1 \
--ostype l26 \
--cpu host --cores 2 --memory 2048 --balloon 1 \
--scsihw virtio-scsi-single \
--net0 virtio,bridge=vmbr0 \
--serial0 socket --vga serial0 \
--agent enabled=1

Using VMID 9000 keeps templates visually separated from real VMs — a convention, not a requirement, but a good one. And efitype=4m,pre-enrolled-keys=1 on the EFI disk is not optional dressing: the CLI’s bare default creates the legacy 2m variant, and when I verified this guide on my own cluster, that VM hung silently before the bootloader — the 4m variant booted cleanly.

2Import the cloud image as the boot disk2 min
Attach the image and make it bootable

qm set 9000 --scsi0 local-lvm:0,import-from=/var/lib/vz/template/iso/noble-server-cloudimg-amd64.img,discard=on,ssd=1
qm set 9000 --boot order=scsi0

import-from copies the downloaded image into your VM storage as the template’s disk. Don’t worry that it’s only ~3.5 GB — clones grow their disks later.

3Add the cloud-init drive1 min
The drive cloud-init reads on first boot

qm set 9000 --ide2 local-lvm:cloudinit

This is the magic piece: a tiny virtual CD-ROM Proxmox regenerates for every clone, carrying that clone’s personal user, key, and network settings.


Task 3: Convert it to a template

1Freeze the master30 sec
One-way door — templates never boot again

qm template 9000

The VM’s icon changes in the web UI and Proxmox now refuses to start it. That’s the point: the master can never drift, so every clone starts from the same known-good state. (Official cloud images ship with a blank machine-id, which prevents the classic duplicate-DHCP-lease problem — see the FAQ if you build a template from a hand-installed VM instead.)


Task 4: Clone and personalize

1Clone the template30 sec
A new VM in one command

qm clone 9000 141 --name web01 --full

--full makes an independent copy. On thin-provisioned storage you can drop it to get a linked clone — near-instant and space-efficient, at the cost of depending on the template’s base disk. For a small homelab, full clones are the simpler default.

2Give it a user, a key, and an IP1 min
Personalize via cloud-init

qm set 141 --ciuser ubuntu --sshkeys ~/.ssh/id_ed25519.pub
qm set 141 --ipconfig0 ip=10.0.0.41/24,gw=10.0.0.1
qm resize 141 scsi0 +28G

Each flag maps to the VM’s Cloud-Init tab in the web UI, where you can see and edit the same values. --ipconfig0 ip=dhcp works too if you’d rather let your router assign the address. The resize grows the tiny cloud-image disk to a useful 32 GB total — cloud-init expands the filesystem to match on the next boot, automatically.

3Boot and log in1 min
First boot — already configured

qm start 141
ssh ubuntu@10.0.0.41

No console, no installer, no password prompts — the VM comes up with your user created and your key installed. First boot takes a little longer than usual while cloud-init does its one-time work; every boot after that is normal speed.

Warning

One honest gotcha from verifying this on my own cluster: Ubuntu’s cloud image does not ship the qemu-guest-agent package, so IP reporting and clean shutdowns don’t work until you install it. Either add it per clone (ssh in and sudo apt install -y qemu-guest-agent) or bake it into the template once before the qm template step with virt-customize -a noble-server-cloudimg-amd64.img --install qemu-guest-agent (from libguestfs-tools). The --agent enabled=1 flag on the template means Proxmox starts listening the moment the package lands.


When to use this (and when not to)

Cloud-init templates shine for anything you create more than once: Docker hosts, test machines, cluster workers, short-lived experiment boxes. The template is also the natural base for infrastructure-as-code tools — Terraform’s Proxmox provider clones these exact templates.

They’re the wrong tool for one-off appliances with their own installers (a firewall distro, TrueNAS) — those still want the traditional ISO route. And if the workload is Linux-only and doesn’t need its own kernel, remember that an LXC container is lighter than any VM, cloned or not.

A closing reminder: every IP, VMID, storage name, and username above is a placeholder from a dummy network — substitute your own values throughout.


Related posts:

Comments

Comments are powered by GitHub Discussions — sign in with a GitHub account to join the conversation.