Building a Reusable Proxmox Cloud-Init Template

· Rack Notes


Installing Linux interactively is useful once. Repeating the installer for every small VM is not. A cloud image plus Proxmox Cloud-Init turns that manual installation into a repeatable template that can produce a ready-to-use guest in minutes.

The example below uses placeholder IDs, storage names, addresses, and URLs. Check the current image checksum from the distribution before importing it.

Download and inspect the image #

Create a working directory on the Proxmox node and download the current cloud image from the distribution's official image server. The URL here is deliberately generic:

1mkdir -p /var/lib/vz/template/cloud
2cd /var/lib/vz/template/cloud
3curl -fLO https://cloud-images.example.invalid/linux/current-server-cloudimg-amd64.img

Verify the publisher's checksum or signature before using the file. Cloud images become the root disks of every clone, so authenticity matters more than download convenience.

Create the base VM #

Choose an unused VM ID and match the bridge, storage, and CPU type to the local environment:

 1qm create 9000 \
 2  --name linux-cloud-template \
 3  --memory 2048 \
 4  --cores 2 \
 5  --cpu host \
 6  --net0 virtio,bridge=vmbr0
 7
 8qm importdisk 9000 \
 9  /var/lib/vz/template/cloud/current-server-cloudimg-amd64.img \
10  local-lvm
11
12qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
13qm set 9000 --ide2 local-lvm:cloudinit
14qm set 9000 --boot order=scsi0
15qm set 9000 --serial0 socket --vga serial0
16qm set 9000 --agent enabled=1

The imported disk becomes scsi0; the separate Cloud-Init drive supplies instance-specific metadata. Serial console support is useful because many cloud images are designed to expose boot output there. Enabling the QEMU guest agent in Proxmox only helps if the image also contains and runs the agent package.

Increase the template disk before cloning if the downloaded image is too small:

1qm resize 9000 scsi0 16G

Do not boot the base VM merely to customize it by hand. Every manual change makes the template harder to reproduce. Prefer Cloud-Init settings, a documented image-building process, or configuration management after first boot.

Set safe defaults #

Provide a public SSH key and let DHCP handle the first test clone:

1qm set 9000 --ciuser labadmin
2qm set 9000 --sshkeys /root/template-keys/labadmin.pub
3qm set 9000 --ipconfig0 ip=dhcp
4qm set 9000 --nameserver 192.0.2.53

Never place a private key in Cloud-Init configuration. Avoid password login for the template; if a temporary password is unavoidable, rotate or remove it immediately after provisioning.

Convert the stopped VM to a template:

1qm template 9000

Clone and customize an instance #

A full clone is independent of the template's storage. A linked clone is faster and smaller but retains a dependency on its base disk. For a durable service, the full clone is usually easier to reason about:

1qm clone 9000 120 --name dns-a --full true --storage local-lvm
2qm set 120 --ipconfig0 ip=192.0.2.120/24,gw=192.0.2.1
3qm set 120 --onboot 1
4qm start 120

Wait for Cloud-Init to finish before judging the result. Inside the guest, cloud-init status --wait reports completion. Then verify the hostname, address, SSH access, resolver configuration, disk size, and guest agent.

If the clone does not receive the expected settings, inspect rather than re-cloning immediately. The Proxmox hardware view should show a Cloud-Init drive, and the Cloud-Init panel should show the generated user, key, and network values. Regenerate the image after changing those values. In the guest, the Cloud-Init logs under /var/log usually distinguish a metadata problem from a network or package problem.

Keep the first clone disposable. Test shutdown from Proxmox, confirm that the reported IP address is correct, and verify that filesystem expansion used the new virtual disk size. Those checks catch most template mistakes before the VM receives application data.

Treat templates as replaceable artifacts #

A template should have a documented source image, creation command, and refresh date. When the distribution publishes a newer image, build a new template ID, test a clone, and migrate future deployments to it. Rebuilding is safer than accumulating years of opaque changes in one golden VM.

The payoff is not just faster provisioning. A repeatable template makes failed experiments cheap: delete the guest, clone a clean one, and continue with a known starting point.

last updated: