Proxmox Packer templates for RHEL 8/9/10 and Ubuntu 22.04/24.04/26.04 — kickstart/autoinstall, Ansible, Vault-signed SSH certs (repo + overview)

chungus

New Member
Mar 23, 2026
3
0
1
Sharing a Packer setup I've been using to build both RHEL and Ubuntu VM templates on Proxmox — same repo, same shared Ansible provisioning, different install automation per distro family. Overview of the whole process below, repo linked at the bottom.

What it builds

VM templates for RHEL 8.10, 9.0–9.8, 10.0–10.2, and Ubuntu Server 22.04, 24.04, 26.04 LTS, using HashiCorp Packer's proxmox-iso builder.

RHEL builds

  1. Unattended install via Anaconda kickstart. Delivery is configurable per Proxmox cluster — either over Packer's built-in HTTP server, or via a CD labeled OEMDRV that Anaconda auto-detects. I ended up needing the CD path on a couple of clusters where the build VLAN has no route back to wherever Packer/CIis actually running, so both modes are supported and picked per cluster rather than hardcoded.
  2. No subscription needed — the build mounts the install DVD itself as a local yum repo (BaseOS + AppStream) instead of registering with Red Hat.

One RHEL-specific gotcha worth flagging: RHEL 8 ships Python 3.6 as the system default, but Ansible's dnf module needs bindings that only exist for that 3.6 install, while Ansible itself needs 3.8+. The build installs Python 3.9 alongside and points Ansible at it, while letting the dnf module keep using the system default where its bindings actually live — otherwise you get confusing failures that look like a missing package rather than an interpreter mismatch.

Ubuntu builds

  1. Unattended install via cloud-init autoinstall — same HTTP-or-seed-ISO choice per cluster as the RHEL builds, for the same reason.
  2. Template cleanup matters more here than for RHEL. Ubuntu's installer (subiquity) leaves its own GRUB config and cloud-init overrides behind after install, which if left in place will make every VM cloned from the template re-run the installer/autoinstall flow on first boot instead of doing a normal cloud-init first-boot. Cleanup strips those out and regenerates GRUB with a clean kernel command line before the template is sealed — easy to miss the first time since nothing about your own provisioning looks wrong when it happens.

Shared across both

  • Ansible provisioning over SSH — same role for both distro families: OS hardening, Vault-signed SSH certificate trust fetched from Vault and written into sshd_config (so any VM cloned from either template accepts Vault SSH certs immediately, no post-deploy config step needed), Vault client installed.
  • Cleanup for cloning — machine-id reset, cloud-init state reset, build user removed.
  • Per-cluster variable files — the same template definitions build cleanly across multiple Proxmox clusters/sites without duplicating the HCL.

Repo

https://github.com/pizzle85-maker/packer-proxmox-linux

Provisioning is handled by a shared Ansible role, also public: https://github.com/pizzle85-maker/ansible-role-packer-os-base

Happy to answer questions if you're setting up something similar.
 
Well, I'm also using Packer to build VM templates for our PVE nodes.

When updating a template, to add an extra layer of security, I usually use the bastion option for the proxmox-clone source:

ssh_bastion_host = var.bastion_host
ssh_bastion_username = var.ssh_username
ssh_bastion_private_key_file = var.ssh_private_key_file


Hope this helps!