๐ŸŸข Network Status| First month from $2.00 โ€” fully managed | Contact Support
Skip to content
Need help? Real engineers available 24/7. Average response under 15 minutes. Open a support ticket โ†’

Proxmox Templates โ€” VM Provisioning Guide โ€‹

Proxmox templates let you provision new VMs in seconds by cloning a pre-configured base image. Combined with cloud-init, each clone boots with a unique hostname, SSH key, and IP configuration automatically.

What is a cloud-init template? โ€‹

A cloud-init template is a VM that has been:

  1. Installed with a minimal OS
  2. Cleaned of unique identifiers (SSH host keys, machine ID)
  3. Configured with cloud-init to accept per-clone configuration
  4. Converted to a Proxmox template (made non-bootable as a standalone VM)

When you clone it, cloud-init applies the hostname, SSH keys, and network config on first boot.

Creating a template (AlmaLinux 9 example) โ€‹

Step 1 โ€” Download the cloud image โ€‹

bash
# On your Proxmox host
cd /var/lib/vz/template/iso

wget https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2

Step 2 โ€” Create the VM โ€‹

bash
# Create a VM with ID 9000
qm create 9000   --name "almalinux-9-template"   --memory 2048   --cores 2   --net0 virtio,bridge=vmbr0   --ostype l26   --agent enabled=1

# Import the cloud image as disk
qm importdisk 9000 AlmaLinux-9-GenericCloud-latest.x86_64.qcow2 local-lvm

# Attach disk as primary drive
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0

# Add cloud-init drive
qm set 9000 --ide2 local-lvm:cloudinit

# Set boot order
qm set 9000 --boot c --bootdisk scsi0

# Add serial console (required for cloud images)
qm set 9000 --serial0 socket --vga serial0

Step 3 โ€” Configure cloud-init defaults โ€‹

bash
qm set 9000   --ciuser root   --cipassword "$(openssl passwd -6 'changeme')"   --sshkeys /root/.ssh/authorized_keys   --ipconfig0 ip=dhcp   --nameserver "8.8.8.8 1.1.1.1"

Step 4 โ€” Convert to template โ€‹

bash
qm template 9000

The VM is now a template. It cannot be started directly โ€” only cloned.

Cloning and deploying a new server โ€‹

bash
# Clone the template to VM ID 101 with a new disk
qm clone 9000 101   --name "web-server-01"   --full   --storage local-lvm

# Set VM-specific cloud-init values
qm set 101   --ipconfig0 ip=10.0.0.10/24,gw=10.0.0.1   --ciuser root   --hostname web-server-01.yourdomain.com

# Resize disk (optional โ€” expand from template default)
qm resize 101 scsi0 +20G

# Start the VM
qm start 101

The VM boots, cloud-init runs, and within 30โ€“60 seconds it's accessible via SSH at the configured IP.

Automating with a script โ€‹

bash
#!/bin/bash
# Usage: ./deploy.sh <vmid> <hostname> <ip> <gateway>
VMID=$1
HOSTNAME=$2
IP=$3
GW=$4
TEMPLATE=9000

qm clone $TEMPLATE $VMID --name "$HOSTNAME" --full --storage local-lvm
qm set $VMID --ipconfig0 ip=$IP/24,gw=$GW --hostname $HOSTNAME
qm resize $VMID scsi0 +10G
qm start $VMID
echo "VM $VMID ($HOSTNAME) starting at $IP"

Maintaining templates โ€‹

Update your template periodically by:

  1. Cloning the template to a temporary VM
  2. Starting it and running OS updates (dnf update -y)
  3. Running cloud-init cleanup: cloud-init clean --logs
  4. Shutting down the VM
  5. Converting back to template: qm template TMPVMID
  6. Deleting the old template and renaming the new one
โœ“
Snapshot before converting back
Take a snapshot of the updated VM before converting to template, in case the update introduces issues and you need to roll back.

Managed hosting that actually manages.