Template preparation
I started from an Ubuntu cloud image and installed qemu-guest-agent into it so the hypervisor could exchange state and configuration with the guest.
virt-customize -a ubuntu-image-cloud.img --install qemu-guest-agent
Create and import
I created a small base VM, imported the prepared image into the local ZFS storage and attached it through the VirtIO SCSI controller.
qm create 2222 --name "ubuntu-cloudinit-template" --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0
qm importdisk 2222 ubuntu-image-cloud.img local-zfs
qm set 2222 --scsihw virtio-scsi-pci --scsi0 local-zfs:vm-2222-disk-0
Boot and cloud-init
The imported disk became the primary boot device. I then attached a cloud-init drive, enabled a serial console and turned on the guest agent.
qm set 2222 --boot c --bootdisk scsi0
qm set 2222 --ide2 local-zfs:cloudinit
qm set 2222 --serial0 socket --vga serial0
qm set 2222 --agent enabled=1
Reusable deployment
Finally, I converted the VM to a template. The platform could clone that template for each new instance and pass hostname, networking, credentials and other requested values through cloud-init.
qm template 2222