TIL: How to Create a Template VM Disk Image

Published on Jan 3, 2025
In Gistful Musings
Comments and Reactions

While experimenting with dqlite, I needed to create multiple virtual machines from a custom template to manually test a few scenarios. cloud-init combined with one of the cloud images from here would have worked, but I wanted to avoid waiting for the VM to boot and configure itself each time I spun up a new instance.

After some research, I discovered virt-sysprep, which turned out to be the perfect tool for the task. From the official documentation:

Virt-sysprep can reset or unconfigure a virtual machine so that clones can be made from it. Steps in this process include removing SSH host keys, removing persistent network MAC configuration, and removing user accounts. Virt-sysprep can also customize a virtual machine, for instance by adding SSH keys, users or logos. Each step can be enabled or disabled as required.

Below, I'll document the steps I followed to create a custom template VM disk image.

Prerequisites

  1. A Linux host or VM
  2. virt-sysprep (install libguestfs-tools on Ubuntu/Debian)
  3. [Optional] ovftool (can also be installed with brew on macOS)

Steps

  1. Create a virtual machine, configure it as needed, and install the required packages (e.g. open-vm-tools).

  2. Shutdown the VM.

  3. [Optional] Use ovftool to Convert the VM into an OVF (e.g. ovftool /path/to/template.vmx /output/path/to/template.ovf)

  4. Use virt-sysprep to "unconfigure" the disk image:

    ops=$(virt-sysprep --list-operations | egrep -v 'fs-uuids|lvm-uuids' | awk '{ printf "%s,", $1}' | sed 's/,$//')
    sudo virt-sysprep -a /path/to/disk.vmdk --hostname localhost --remove-user-accounts ansible --enable $ops --firstboot-command 'dpkg-reconfigure openssh-server' --root-password password:changeme
    
  5. Create a new VM from the disk image.