Anyone rolling out virtual machines regularly on Proxmox VE 8.x sooner or later faces the question: do I go with classic VM templates and linked clones — or with Cloud-Init-based provisioning? Both approaches are officially supported, both work reliably, and both have their own target audience in practice. The choice not only drives your storage footprint, but also how quickly your team can react to security patches and how cleanly the whole thing embeds into an IaC pipeline.
In this article we walk you through how both patterns work, where the technical limits lie, and in which scenarios we recommend one path or the other in our customer projects.
Two patterns, two philosophies
A VM template in Proxmox is nothing more than a VM that has been moved into a read-only state via qm template <vmid>. From that point on it can no longer be started, but cloned as often as you like — either as a full clone (complete copy) or as a linked clone (delta layer on top of the template disk). Templates embody the concept of immutable base images: they are built cleanly once, hardened, patched, and then never modified.
Cloud-Init, on the other hand, is a vendor-neutral standard from the public-cloud world (Canonical, originally for Ubuntu on EC2). Proxmox supports Cloud-Init via a special CD-ROM-like disk that hands metadata to a generic cloud-image VM: hostname, IP address, SSH keys, users, network configuration and optionally full user-data scripts. The base disk stays generic; the individual configuration is created on first boot.
Put simply: templates define what is inside, Cloud-Init defines how it configures itself. In many professional setups we combine both.
Pattern 1: classic template with linked clone
The classic path fits extremely well in environments where many VMs benefit from the same base image — VDI, RDS farms or homogeneous Windows server fleets, for example. The workflow is straightforward:
# 1. Install, harden and patch a base VM
qm create 9000 --name tpl-debian12-base --memory 2048 --cores 2 \
--net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single
qm importdisk 9000 debian-12-generic-amd64.qcow2 local-zfs
qm set 9000 --scsi0 local-zfs:vm-9000-disk-0,discard=on,ssd=1
qm set 9000 --boot order=scsi0 --agent enabled=1
# 2. Boot the VM, configure it, shut it down
# 3. Convert into a template
qm template 9000
# 4. Create a linked clone
qm clone 9000 101 --name web01 --full 0
The --full 0 flag creates a linked clone: the new VM points at the template disk and only stores changes as a delta. The upside: a clone is created in seconds and initially consumes only a few MB. The downside: every clone is permanently anchored to the template. If the template is deleted, all children become unusable. A “refresh” to a newer base image requires rolling out completely new VMs.
Pattern 2: Cloud-Init provisioning
Cloud-Init plays to its strengths wherever VMs differ in network, hostname, certificates or user setup — practically every time you roll out Linux workloads dynamically. Instead of maintaining a self-built image, you download the distribution’s official cloud image (Debian, Ubuntu, Rocky and AlmaLinux all ship these) and attach a Cloud-Init drive:
# Import the cloud image
qm create 9100 --name tpl-ubuntu2404-ci --memory 2048 --cores 2 \
--net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single --serial0 socket
qm importdisk 9100 noble-server-cloudimg-amd64.img local-zfs
qm set 9100 --scsi0 local-zfs:vm-9100-disk-0,discard=on,ssd=1
qm set 9100 --ide2 local-zfs:cloudinit
qm set 9100 --boot order=scsi0 --agent enabled=1
qm template 9100
# Clone and individualise per VM
qm clone 9100 201 --name db01 --full 1
qm set 201 --ipconfig0 ip=10.10.20.11/24,gw=10.10.20.1
qm set 201 --sshkeys ~/.ssh/authorized_keys
qm set 201 --ciuser admin --cipassword $(openssl passwd -6 'secret')
qm start 201
For more complex setups (installing extra packages, enabling systemd units, populating /etc/hosts) you drop a user-data file as a snippet:
#cloud-config
package_update: true
package_upgrade: true
packages:
- qemu-guest-agent
- htop
- fail2ban
runcmd:
- systemctl enable --now qemu-guest-agent
- systemctl enable --now fail2ban
write_files:
- path: /etc/motd
content: |
Managed by DATAZONE -- unauthorized access prohibited.
Place the file under /var/lib/vz/snippets/user-data-db.yaml and reference it:
qm set 201 --cicustom "user=local:snippets/user-data-db.yaml"
Direct comparison
| Criterion | VM template + linked clone | Cloud-Init |
|---|---|---|
| Clone time | Seconds | Seconds to minutes (first-boot setup) |
| Storage overhead | Very low (delta) | Full clone typical, thin provisioning possible |
| Per-VM individualisation | Manual/scripted after the fact | Declarative in the clone command |
| Patch refresh | New template + re-roll | apt upgrade while running |
| Coupling to base | Hard — template must stay | Loose — base image swappable |
| Windows support | Very good (Sysprep) | Limited (needs Cloudbase-Init) |
| IaC-friendliness | Medium | Very good (Terraform, Ansible, Packer) |
| Ideal for | VDI, homogeneous fleets, hardened images | Linux servers, DevOps, multi-tenant |
When to pick which? Our recommendation
We recommend templates with linked clones when you:
- need many nearly identical VMs (e.g. VDI pool, terminal server farm),
- want to maintain a self-controlled, hardened base image (think CIS benchmark),
- need to maximise storage efficiency on ZFS or LVM-thin,
- roll out classic Windows workloads prepared with Sysprep.
Cloud-Init is our recommendation when you:
- provision Linux servers dynamically with individual IP, hostname and package selection,
- use Terraform, Ansible or Packer as an automation layer,
- want frequent refresh cycles of your base images (Ubuntu LTS, Debian Stable),
- serve multi-tenant scenarios with different SSH keys per customer.
In practice we combine both: a self-built Cloud-Init template (created with Packer, hardened, with qemu-guest-agent and monitoring agent) serves as the base, and the individual configuration moves into user-data snippets managed from a Git repository. That way you get the storage efficiency and control of the template world combined with the declarative flexibility of Cloud-Init.
Common pitfalls
- QEMU Guest Agent not enabled: without
--agent enabled=1and the agent installed in the guest,qm shutdown, IP display and snapshot-freeze do not work cleanly. - Cloud-Init caches old configuration: when you re-adjust network or user, you have to run
cloud-init cleaninside the guest — or better, just re-clone. - Linked clones and storage migration: a linked clone cannot easily be moved to another storage — plan that into your storage design.
- Template updates: there is no such thing as “updating” a template. Build a new template with an incremented version number (
tpl-debian12-base-v3) and roll new VMs from it.
Conclusion
Both patterns have their place, and the question is rarely “either or” but “for what”. Anyone running VDI and homogeneous Windows fleets cannot get around classic templates with linked clones. Anyone provisioning a modern Linux server landscape dynamically is significantly faster and more automation-friendly with Cloud-Init. And anyone who combines both gets the maximum efficiency and flexibility out of Proxmox VE.
DATAZONE supports you in designing Proxmox provisioning pipelines, in building reproducible Packer pipelines for Linux base images and in integrating with Terraform or Ansible. Whether greenfield cluster or migration of an existing ESXi estate — reach out to us at kontakt@datazone.de and we will build the provisioning pipeline that fits your team and your change cadence.
More on these topics:
More articles
Proxmox Backup Server vs. Veeam Community: Which When?
Proxmox Backup Server or Veeam Community Edition? Comparison of deduplication, VM limit, multi-hypervisor support and recovery workflows for SMB backup.
Proxmox vGPU with NVIDIA: Getting the License Setup Right
Hands-on guide to NVIDIA vGPU on Proxmox VE 8.2: DLS license server, host driver, guest setup, profile choice and common pitfalls in SMB VDI deployments.
Bash vs. Ansible: When the Jump Is Worth It
Bash scripts or Ansible for your server automation? When idempotency, inventory and playbook reuse actually pay off for growing Linux environments.