Creating a Debian Cloud Image Template for Proxmox

Build reusable VM templates with cloud-init support

Posted by Rene Welches on Friday, January 23, 2026
Last Modified on Tuesday, February 17, 2026

Overview

This guide walks through creating a Debian cloud image template in Proxmox. Cloud images are pre-built, minimal OS images optimized for virtualized environments, featuring a slimmed-down kernel with minimal hardware drivers and pre-installed cloud-init for automated configuration.

They enable automated configuration of hostname, SSH keys, networking, and more at first boot. Sure, you could also create a template manually, set up SSH keys within the template and set up a default user, but that would be just half the fun and you would still use a bloated OS with a lot of stuff you don’t need.

What We’re Doing

We are following for the most part the official document on Proxmox Cloud Images. But instead of using Ubuntu we are going to use Debian 13.

Step-by-Step Guide

Step 1: Download the Debian Cloud Image

SSH into one of your Proxmox nodes and download the official Debian cloud image:

# Navigate to the directory where proxmox stores iso images
cd /var/lib/vz/template/iso

# Download the latest Debian 13 (trixie) generic cloud image
wget https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2

and verify the checksums.

Note: Proxmox will not allow you to import an image with an ending qcow2 via the UI. You will have to do this via command line interface.

Step 2: Create a New VM

Create a VM that will become our template:

# Create a new VM with ID 1001 (choose an unused ID)
qm create 1001 --name debian-13-cloud-template --memory 2048 --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-pci

1001: Your VM ID, choose an unsed ID. --name debian-13-cloud-template: The name of the VM aka template. --memory 2048: The amount RAM for the VM --cores 2: The number of CPU cores for the VM --net0 virtio,bridge=vmbr0: Configures the first network interface. virtio is a paravirtualized network adapter that provides better performance than emulated hardware because the guest OS knows it’s virtualized. bridge=vmbr0 connects this interface to the Proxmox bridge vmbr0, which is typically the default bridge linking VMs to your physical network. Without this parameter, the VM would have no network connectivity. --scsihw virtio-scsi-pci: Sets the SCSI controller type. virtio-scsi-pci is a paravirtualized SCSI controller that offers better performance and more features than emulated controllers (like LSI). It supports advanced features like TRIM/discard for SSDs, multiple queues for improved I/O parallelism, and hot-plugging of disks. This is the recommended controller type for modern Linux guests.

Step 3: Import the Cloud Image as Disk

Import the downloaded qcow2 image as the VM’s disk:

# Import the disk to your storage (adjust 'local-lvm' to your storage name)
qm importdisk 1001 debian-13-generic-amd64.qcow2 local-lvm

1001: The VM ID to import the disk into (must match the VM created in Step 2). debian-13-generic-amd64.qcow2: The source disk image file you downloaded. It needs to be the full path if you are not running it the directory where you downloaded the image e.g. /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2 local-lvm: The target storage where the disk will be stored. Adjust this to match your Proxmox storage name (e.g., local-zfs, ceph-pool, etc.).

Step 4: Attach the Disk to the VM

Configure the VM to use the imported disk:

# Attach the disk as scsi0
qm set 1001 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-1001-disk-0

# Set the boot order
qm set 1001 --boot c --bootdisk scsi0

Step 5: Add Cloud-Init Drive

Add a cloud-init drive for automated configuration:

# Add cloud-init CD-ROM drive
qm set 1001 --ide2 local-lvm:cloudinit

# Enable serial console for cloud-init output, Debian images require a serial console
qm set 1001 --serial0 socket --vga serial0

Some images rely on serial0 being present as a display option.

Step 5: Convert the VM to a template

qm template 1001

Step 6: Configure Cloud-Init Defaults

This step is optional, and the cloud-init values can be set at VM creation e.g. via Terraform. Set default cloud-init parameters (change as needed by your use case):

# Set default user (optional)
qm set 1001 --ciuser admin

# Set SSH public key (recommended)
qm set 1001 --sshkey ~/.ssh/id_rsa.pub

# Configure IP via DHCP
qm set 1001 --ipconfig0 ip=dhcp

# When using DHCP a running qemu agent is required, otherewise any cloned VM will not get an IP address. Enable the qemu agent:
qm set 1001 --agent 1

Step 7: Resize the Disk (Optional)

The cloud image comes with a small disk. Resize if needed:

# Add 20GB to the disk
qm resize 1001 scsi0 +20G

All the Steps in a Single Bash Script

#!/bin/bash
set -e

TEMPLATE_ID=$(pvesh get /cluster/nextid) || { echo "Failed to get ID"; exit 1; }
TEMPLATE_NAME="debian-13-cloudinit-tmplt"
TEMPLATE_IMG=/mnt/pve/minis-cluster-nfs/template/iso/debian-13-generic-amd64.qcow2
STORAGE="local-lvm"

if [[ ! -f "$TEMPLATE_IMG" ]];
    then echo "$TEMPLATE_IMG"
    exit 1
fi

echo "Creating VM $TEMPLATE_ID with name $TEMPLATE_NAME"
qm create $TEMPLATE_ID --name $TEMPLATE_NAME --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-pci

echo "Importing disk..."
qm importdisk $TEMPLATE_ID $TEMPLATE_IMG $STORAGE

echo "Configuring VM..."
echo "Attaching Disk..."
qm set $TEMPLATE_ID --scsihw virtio-scsi-pci --scsi0 ${STORAGE}:vm-${TEMPLATE_ID}-disk-0
echo "Setting boot order..."
qm set $TEMPLATE_ID --boot order=scsi0 --serial0 socket --vga std
echo "Adding Cloud-Init Drive..."
qm set $TEMPLATE_ID --ide2 ${STORAGE}:cloudinit

echo "Configure Cloud-Init Defaults..."
echo "Setting ci user..."
qm set $TEMPLATE_ID --ciuser admin
echo "Setting up puplic ssh key..."
qm set $TEMPLATE_ID --sshkey ~/.ssh/id_rsa.pub
echo "Enabling DHCP..."
qm set $TEMPLATE_ID --ipconfig0 ip=dhcp
echo "Enabling qemu-guest-agent..."
qm set $TEMPLATE_ID --agent 1
echo "Set ci user password..."
qm set $TEMPLATE_ID --cipassword

echo "Converting to template..."
qm template $TEMPLATE_ID

echo "Resizing Disk"
qm resize $TEMPLATE_ID scsi0 +17G

echo "Template $TEMPLATE_ID created successfully!"

Update (February 2026): When I had to re-create the template, the guest agent wouldn’t start. In this case, do not convert the VM to a template right away. Instead, start the VM first and install the agent with sudo apt install qemu-guest-agent. If you are using a custom root CA (as I do), it is also recommended to add it to the Linux certificate store. You can then shut down the VM and convert it to a template.

Deploying VMs from the Template

Clone the Template

# Full clone (independent copy) - replace 101 with a availble VM ID.
qm clone 1001 101 --name my-debian-vm --full

# Or linked clone (shares base image, saves space)
qm clone 1001 101 --name my-debian-vm

Configure the Clone

# Set hostname and other cloud-init options
qm set 101 --ciuser myuser --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1

Start the VM

qm start 101

Cloud-Init Configuration Options

ParameterDescriptionExample
--ciuserDefault useradmin
--cipasswordUser passwordsecretpass
--sshkeySSH public key file~/.ssh/id_rsa.pub
--ipconfig0Network configurationip=dhcp or ip=x.x.x.x/24,gw=x.x.x.x