Sign in to your XDA account
Native support for LXCs is one of Proxmox’s biggest selling points, but there are situations where you’ll want the superior isolation provisions offered by virtual machines. While my self-hosted services run inside containers, I use VMs quite a lot in my PVE home lab. My Windows 11 and Arch Linux dev environments run inside virtual machines, and the same holds true for all the cool Linux and OpenBSD flavors I tinker with during my distro-hopping misadventures.
That said, I often create disposable virtual machines for experiments, which get destroyed when I run into unrecoverable errors – or once I’ve finished documenting everything. Up until now, I’ve mostly relied on custom templates for my test VMs. But after encountering Cloud-Init, I’ve since switched…
Sign in to your XDA account
Native support for LXCs is one of Proxmox’s biggest selling points, but there are situations where you’ll want the superior isolation provisions offered by virtual machines. While my self-hosted services run inside containers, I use VMs quite a lot in my PVE home lab. My Windows 11 and Arch Linux dev environments run inside virtual machines, and the same holds true for all the cool Linux and OpenBSD flavors I tinker with during my distro-hopping misadventures.
That said, I often create disposable virtual machines for experiments, which get destroyed when I run into unrecoverable errors – or once I’ve finished documenting everything. Up until now, I’ve mostly relied on custom templates for my test VMs. But after encountering Cloud-Init, I’ve since switched to it when deploying expendable virtual machines. Sure, it has a couple of caveats, but it’s hands-down the most efficient option for CLI-heavy distros that require slight configuration tweaks before you can spin them up.
Cloud-Init offers a quick way to deploy VMs
It’s even faster than custom templates
Being able to create templates from custom virtual machine setups and use them for deploying newer instances is quite useful when you tinker with VMs as much as I do. Not only are you spared from installing the operating system again, but you also get a fully-configured VM right off the bat.
Unfortunately, this method has some caveats. Let’s say I created a VM template featuring a static IP address, set up an SSH key, and created a user account with my name. If I wanted to modify any of these settings, I’d have to spin up a new VM, log in to it, and then make all the necessary changes. That can get rather annoying when I want to deploy multiple instances of the same virtual machine but with slightly different parameters.
Cloud-Init is a bit like custom templates, except it differs on two major accounts. For one, you can grab a pre-made cloud-ready image instead of building one yourself. But the real draw is that most of the essential VM settings can be tweaked from Proxmox’s web UI, so you don’t have to log into the virtual machine just to modify them.
Creating Cloud-Init templates requires a little effort
Remember to resize the Cloud-Init storage drive
Although custom templates are easier to build, their Cloud-Init counterparts need some elbow grease. For my primary Cloud-Init template, I decided to use Ubuntu’s cloud-ready image as a base. So, I headed to the** ISO **section of the local drive, pressed the Download from URL button, and entered the address for the latest Ubuntu Noble cloud-ready image. Once it was downloaded, I set up a typical virtual machine using the VM creation wizard, though I left the Storage section completely blank.
With that, it was time to don my CLI hat, as I had to run a couple of Shell commands inside the Proxmox host to configure the VM that would serve as the template. First, I had to run the qm set vm_id –scsi0 local-lvm:0,import-from=/var/lib/vz/template/iso/image_name.img command to connect the newly downloaded Ubuntu image with the VM. Since I also needed a virtual CD-ROM for the Ubuntu image to work, I executed qm set vm_id –ide2 local-lvm:cloudinit. To ensure maximum compatibility, I added a VGA serial console module to it by running qm set vm_id –serial0 socket –vga serial0.
Next, I had to overwrite the Boot Order within the VM’s Options tab to ensure it would use the SCSI drive from earlier as the primary storage device. But since I didn’t want to run out of space, I used the qm disk resize vm_id scsi0 50G command to bolster its storage capacity.
By now, I could access the Cloud-Init tab to modify the user account, network, and SSH settings for the template, and after going ahead with the changes, I right-clicked on the VM and chose the** Convert to template** option.
It meshes well with automation tools
Although being able to whip out fully-configured virtual machines is pretty useful on its own, Cloud-Init’s real utility comes into light when you pair it with Ansible and Semaphore. The former is my favorite automation utility for post-setup tweaks, while the latter is a solid web UI for managing Ansible artifacts. My preferred approach involves creating a new VM from the template and modifying its IP address and user account from the Cloud-Init tab. Then, I add the network details to the Hosts file, while the username and password stay inside Key Store variables on Semaphore’s web UI.
With the artifacts ready, I run Ansible playbooks to automatically install my favorite packages on all the Cloud-Init virtual machines. I rely on Proxmox’s interface to spin up the Cloud-Init images, but I plan to create Terraform configurations to automatically deploy them without any input from my end.