Published 8 minutes ago
Maker, meme-r, and unabashed geek, Joe has been writing about technology since starting his career in 2018 at KnowTechie. He’s covered everything from Apple to apps and crowdfunding and loves getting to the bottom of complicated topics. In that time, he’s also written for SlashGear and numerous corporate clients before finding his home at XDA in the spring of 2023.
He was the kid who took apart every toy to see how it worked, even if it didn’t exactly go back together afterward. That’s given him a solid background for explaining how complex systems work together, and he promises he’s gotten better at the putting things back together stage since then.
This year …
Published 8 minutes ago
Maker, meme-r, and unabashed geek, Joe has been writing about technology since starting his career in 2018 at KnowTechie. He’s covered everything from Apple to apps and crowdfunding and loves getting to the bottom of complicated topics. In that time, he’s also written for SlashGear and numerous corporate clients before finding his home at XDA in the spring of 2023.
He was the kid who took apart every toy to see how it worked, even if it didn’t exactly go back together afterward. That’s given him a solid background for explaining how complex systems work together, and he promises he’s gotten better at the putting things back together stage since then.
This year has been somewhat of a revelation for my home lab, as I finally moved my mess of containers and virtual machines from my Windows desktop and NAS to a dedicated mini PC with Proxmox as the hypervisor. Then I got really excited about HA clustering, only to decide that those mini PCs weren’t powerful enough and move the whole shebang onto a Strix Halo mini PC with tons of RAM.
It’ll be going onto a dedicated server in a 6U chassis after the holidays have quietened down, but the constant shifting in scale has taught me one thing. I need to be smarter about the images I use to create my containers and VMs, and also that automation tools are my next knowledge gap.
Proxmox has a decent selection of base images and turnkey options for individual services, but I’m more used to other Linux flavors, so I don’t use those much. I’ve been manually installing VMs and converting containers, and it’s time to stop. Proxmox lets you create your own templates in more than one way, and I’ve just been slacking off.
Proxmox has tons of base images, but they all have one thing in common
Base means no recent updates
Proxmox offers a decent selection of images, but they have one issue: they’re not always up to date. That’s a pain, because part of the point of using an existing template is that I don’t have to go through the hassle of installing, updating, and sanitizing VMs from ISO installers.
But once you’ve set up any VM or LXC on your host, you can create a template from it, then use that template to carbon-copy your way to home lab greatness. All it takes is you to set things up as usual, then right-click the virtual guest in the list and select Create Template. But that’s not always the best approach, and Proxmox offers more choices for specialized use cases.
Cloud-Init makes things a little faster
Most anything that Proxmox supports can be built from custom templates, but you still have to log in to the virtual guest once it’s running to change any settings. That’s fine if you’re only initializing one new VM, but what if you want a few to play with clustering, and each needs slightly different settings? That’s more of a chore, but Cloud-Init makes it substantially easier.
Now, not the initial setup, mind you. Getting a Cloud-Init template set up takes a little longer because you have to run a combination of shell commands to get the VM into a usable state, then you can add details like user accounts, networking, and SSH settings to the VM. That’s okay for testing, but adding credentials like that to a VM template is a big no-no in production. I’ll get to how to add those using some automation tools a little later.
And don’t forget you can use OCI registry images now
Proxmox VE 9.1 added yet another way of making your own images by pulling them directly from your OCI registry of choice. That’s Docker, Containerd, and Podman, just to be sure, and it doesn’t pull and run the containers as written; instead, it converts them to a LXC for you once it’s been downloaded.
No more manually pulling the container, running it, and exporting the running container to an archive file for Proxmox to use, which is fantastic because that was a pain every time. Head to the local storage pool and smash the Pull from OCI Registry in the CT Templates section. Put in your favorite image repositories as if you were using docker pull from the command line. For example, adding radhifadlillah/shiori to the Reference box, and using latest in the Tag box gets you a download button.
Then it’s the same as creating any other base image: deploy the container, right-click the container name, and select Convert to template.
Credit: Source: Proxmox
Proxmox
Let’s automate things a little more with Packer
Hashicorp is the king of Infrastructure-as-Code (IoC)
All the methods so far will work and will save you time. But we can always optimize a little more in the home lab, and there really aren’t any finer tools than those made by HashiCorp. We’ve covered Terraform with Proxmox before, but we’re going to use a different tool, Packer, which lets you define the process of making machine images, including Docker, LXC, and VM,s and have it automatically create the image, with updates, user accounts, and any other information we want.
It’s like watching your computer come alive and create a VM for you, and it’s really something fantastic to see. I mean, I grew up in the era of computer intelligence in movies, with computers talking back to the user through the CLI, and seeing this level of automation brings back all those feelings of wonder.
Credit: Source: HashiCorp
Packer
Time to start our VM template
We need a base image and a definition file
Like any other Infrastructure-as-Code tool, Packer uses simple-to-follow text files as the build instructions. I’ll need a text file named **ubuntu-2510-desktop.pkr.hcl **open in Cursor, my current favorite editor, and to start it off, we’ll add the instructions to make Packer download the Proxmox plugin that it needs to interact with my PVE node.
# ubuntu-2510-desktop.pkr.hclpacker { required_plugins { proxmox = { version = ">= 1.1.1" source = "github.com/hashicorp/proxmox" } }}
I will say I’m not going to put every single section of this file here, as it’ll get long, but I’ll put the general structure. After the Proxmox plugin, we need to tell Packer how to connect to our node by defining our username, password, and the Proxmox node URL. The following section tells Packer where to pull the Ubuntu 25.10 ISO from and that we want it stored in the Proxmox node’s local storage pool.
Then we enter the details we need for the VM, including memory, cores, OS, networking adapter details, and the virtual disks to create. Before the rest of the HCL2 file is created, we can take advantage of Cloud-Init and get Packer to do all the annoying parts of the Ubuntu install for us. First we make a folder called cidata and create **user-data **and meta-data into that folder, which will serve as a mounted CD while Packer is running. Inside the user-data file we add:
#cloud-configautoinstall: version: 1 refresh-installer: locale: en_US.UTF-8 keyboard: layout: us identity: hostname: ubuntu-desktop password: "secretgoeshere" username: ubuntu ssh: allow-pw: false install-server: true authorized-keys: - "ssh-ed25519 ssh-key-you-generated name@email" package_update: true package_upgrade: true packages: - qemu-guest-agent - cloud-init
This tells cloud-init that it’s not a shell script, tells the system to pull the latest Ubuntu installer before continuing, sets up the locale and keyboard layout, the username and password, etc., for the VM, the SSH key, and tells Packer to update the installed OS and add the qemu-guest-agent and cloud-init packages. You can add any packages you want here, like your favorite tools or apps, but the more you add, the longer the process will take.
Then back to the HCL2 file, to add a section mounting the cidata folder, and that qemu_agent can find out the IP address of the VM to SSH into. And a section about the correct commands for setting up GRUB and the bootloader; and a name for the VM on the Proxmox node.
At this stage, running "**packer build ./ubuntu-2510-desktop.pkr.hcl" **in a Terminal emulator starts Packer, and you can head over to your Proxmox node to watch the magic unfold. After about ten minutes, Packer will then SSH into the running VM to reset cloud-init ready to turn this VM into a template, and you’re all done.
Proxmox templates are better when you make your own
The power of virtualization platforms like Proxmox is that they enable a virtual blank slate, to create the architecture you want for experimentation and production. Setting up individual containers or VMs is fine when you’re starting out, but your time is better spent on learning other things once you’ve got the basics down.