How to prepare a Cloud-Init Templates with Proxmox

The Story of Cloud-Init Images at Vander Host

This is an article about the preparation of Cloud-Init images for a Proxmox server to automate the deployment of virtual machines. It covers a few common operating system environments such as Debian, Ubuntu, AlmaLinux, Rocky Linux, and CentOS. Vander Host supports all these templates for any of our VPS hosting services and we use these scripts and variations thereof to ensure that our clients have access to the latest operating systems.

TL;DR

  • We have two scripts to try and use
  • If it’s a new Proxmox host, and you want the second script, install the tools first:
    • apt install libguestfs-tools
    • The size of the guest tools on Proxmox VE is about 189 MB
  • We have all the templates below
  • For finer details, see the scripts below that

List of Templates February 2026

We also have Windows templates and can install any other template that you require.

Template Check List 1

  • Is ,ssd=1? It seems no matter what you do on the template, it is still overridden when you deploy.
  • Is protection enabled?
  • Is SCSI Single?
  • Are these installed: qemu-guest-agent, mc, parted, spice-vdagent?
  • How about NUMA?
  • Hotplug
  • Can you SSH with password?
  • What is the deployment username?
    • Preferred username: rocky or whatever (as per /etc/cloud/cloud.cfg)

Template Check List 2

  • Add to Config Option: VM Template|VM Template Debian-13/Debian-13
  • Options:
    • qemu-guest-agent enabled?
    • trim?
    • freeze thaw?

Screenshots available upon request.

Post Creation Checklist

  • PermitRootLogin prohibit-password
  • SSD = 1 no more
  • Guest agent stuff no more
  • Username not debian, should be set in system
  • IP Management system for IPv4 and IPv6
  • Default Display instead of Serial, why do we use  it?
  • spice-vdagent
  • Automatic key addition

Updated 2026 Script

Mount Method

This one doesn’t use libvirt-customize so no need for the apt command.

#!/bin/bash
set -e

DEFAULT_STORAGE="nasXX"
DEFAULT_IMAGE="example.qcow2"
DEFAULT_PKGS_RPM="qemu-guest-agent mc parted mutt"
DEFAULT_PKGS_DEB="qemu-guest-agent mc parted mutt"

read -p "Storage [$DEFAULT_STORAGE]: " STORAGE
STORAGE="${STORAGE:-$DEFAULT_STORAGE}"

read -p "Image [$DEFAULT_IMAGE]: " IMAGE
IMAGE="${IMAGE:-$DEFAULT_IMAGE}"

read -p "VM ID: " TEMPLATE_ID
read -p "Friendly name: " FRIENDLY_NAME

echo "OS family?"
select OS_FAMILY in "RedHat (dnf)" "Debian (apt)"; do
    case $REPLY in
        1) OS_FAMILY="redhat"; break;;
        2) OS_FAMILY="debian"; break;;
        *) echo "Please select 1 or 2";;
    esac
done

if [ "$OS_FAMILY" = "redhat" ]; then
    DEFAULT_PKGS="$DEFAULT_PKGS_RPM"
else
    DEFAULT_PKGS="$DEFAULT_PKGS_DEB"
fi

read -p "Packages to install [$DEFAULT_PKGS]: " PKGS
PKGS="${PKGS:-$DEFAULT_PKGS}"

MOUNTPOINT=/mnt/guestimage
mkdir -p "$MOUNTPOINT"

echo "Mounting image..."
guestmount -a "$IMAGE" -i "$MOUNTPOINT"

echo "Configuring image..."
echo 'nameserver 1.1.1.1' > "$MOUNTPOINT/etc/resolv.conf"

if [ "$OS_FAMILY" = "redhat" ]; then
    chroot "$MOUNTPOINT" dnf install -y $PKGS
    chroot "$MOUNTPOINT" dnf clean all
    sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' \
        "$MOUNTPOINT/etc/ssh/sshd_config"
else
    chroot "$MOUNTPOINT" apt-get update
    chroot "$MOUNTPOINT" apt-get install -y $PKGS
    chroot "$MOUNTPOINT" apt-get clean
    sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' \
        "$MOUNTPOINT/etc/ssh/sshd_config"
fi

echo "Unmounting image..."
guestunmount "$MOUNTPOINT"

echo "Creating VM..."
qm create "$TEMPLATE_ID" --memory 2048 --net0 virtio,bridge=vmbr0
qm importdisk "$TEMPLATE_ID" "$IMAGE" "$STORAGE"
qm set "$TEMPLATE_ID" --scsihw virtio-scsi-single --scsi0 "$STORAGE:vm-$TEMPLATE_ID-disk-0",ssd=1
qm set "$TEMPLATE_ID" --ide2 "$STORAGE:cloudinit"
qm set "$TEMPLATE_ID" --boot c --bootdisk scsi0
qm set "$TEMPLATE_ID" --serial0 socket --vga serial0
qm set "$TEMPLATE_ID" --cpu host --numa 1
qm set "$TEMPLATE_ID" --hotplug cpu,memory,disk,network,usb
qm set "$TEMPLATE_ID" --acpi 1
qm set "$TEMPLATE_ID" --protection 1
qm set "$TEMPLATE_ID" --name "$FRIENDLY_NAME"
qm template "$TEMPLATE_ID"

Virt-Customize Script

Here is the older script that uses virt-customize. We moved away from it after AlmaLinux 10 on Proxmox 9 generation had perpetual problems with DNS resolution. This script has quite a bit of hard coding – so only use it for reference.

#!/bin/bash
set -e

IMG="debian-13-generic-amd64.qcow2"
DEFAULT_PKGS="parted mc mutt spice-vdagent"

read -p "VM ID: " TEMPLATEID
read -p "Friendly name: " FRIENDLY_NAME
read -p "Packages to install [$DEFAULT_PKGS]: " PKGS
PKGS="${PKGS:-$DEFAULT_PKGS}"
PKGS_CSV="${PKGS// /,}"

virt-customize -a "$IMG" --install "qemu-guest-agent,$PKGS_CSV"
virt-customize -a "$IMG" --run-command "sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config"

qm create "$TEMPLATEID" --memory 2048 --net0 virtio,bridge=vmbr0
qm importdisk "$TEMPLATEID" "$IMG" nas05
qm set "$TEMPLATEID" --scsihw virtio-scsi-single --scsi0 "nas05:vm-$TEMPLATEID-disk-0",ssd=1
qm set "$TEMPLATEID" --ide2 nas05:cloudinit
qm set "$TEMPLATEID" --boot c --bootdisk scsi0
qm set "$TEMPLATEID" --serial0 socket --vga serial0
qm set "$TEMPLATEID" --cpu host --numa 1
qm set "$TEMPLATEID" --hotplug cpu,memory,disk,network,usb
qm set "$TEMPLATEID" --protection 1
qm set "$TEMPLATEID" --name "$FRIENDLY_NAME"
qm template "$TEMPLATEID"

Interaction in real-time with the image

guestfish -a Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 -i
vi /etc/ssh/sshd_config

Caveats AlmaLinux 9

  • AlmaLinux crashed with stock KVM64 CPU!
  • AlmaLinux 9 includes /etc/ssh/sshd_config.d/50-cloud-init.conf special include directory which overwrites PasswordAuthentication:

PasswordAuthentication no

Try this: https://forum.proxmox.com/threads/cloud-init-replaces-overwrites-passwordauthentication.57145/

Updated Script: https://github.com/Razva/newbadmin/blob/master/proxmox/cloudinit-generator

  • Example:
  • guestfish -a alma9.qcow2 -i
    • check settings
      • cat /etc/ssh/sshd_config | more
      • #PasswordAuthentication yes
      • #KbdInteractiveAuthentication yes
  • virt-customize PasswordAuthentication? ChallengeResponseAuthentication? UsePAM? Fix cloud-init
    • virt-customize -a alma9.qcow2 –run-command “sed -i ‘s/#PasswordAuthentication yes/PasswordAuthentication yes/g’ /etc/ssh/sshd_config”
    • virt-customize -a alma9.qcow2 –run-command “sed -i ‘s/#KbdInteractiveAuthentication yes/KbdInteractiveAuthentication yes/g’ /etc/ssh/sshd_config”

Caveats Debian Bookworm

Customization explanation:

  • Allow SSH PasswordAuthentication by using SED find and replace. Please note, this is a security risk. If you are going to forget to disable it after you have added keys, then rather just work with keys.
  • Optional for Virtualmin quotas (older versions)
    • linux-image-generic
  • virt-customize -a debian-12-generic-amd64.qcow2 –run-command “sed -i ‘s/PasswordAuthentication no/PasswordAuthentication yes/g’ /etc/ssh/sshd_config”

On Proxmox, you’ll also want to turn on protection and enable the QEMU Guest Agent with fstrim_cloned_disks: Enabled

 

 

 

Notes

virt-customize

A note about Hot Plug

If you want to use Hot Plug on Debian, be sure to read this part of the Proxmox manual that suggests for CPU hotplug, you have to modify the guest. However, in my experience, you don’t. I just works.

https://pve.proxmox.com/wiki/Hotplug_(qemu_disk,nic,cpu,memory)#Kernel_5.15_and_newer

For Linux kernel >=5.15 (e.g. Ubuntu 22.04) you only need the UDEV rule for CPU hotplug:

/lib/udev/rules.d/80-hotplug-cpu.rules

SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1"

Problems with AlmaLinux

AlmaLinux crashes if the CPU isn’t host. You’ll get a Kernel panic on startup. This is well documented on the Proxmox website:

https://forum.proxmox.com/threads/kernel-panic-installing-rocky-or-almalinux.114885/

Here is a screenshot:

Other External References

Share this article

2 thoughts on “How to prepare a Cloud-Init Templates with Proxmox”

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top