# TIL: How to Create a Template VM Disk Image While experimenting with [dqlite](https://dqlite.io/), I needed to create multiple virtual machines from a custom template to manually test a few scenarios. [`cloud-init`](https://cloud-init.io/) combined with one of the cloud images from [here](https://cloud-images.ubuntu.com/noble/current/) 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](https://libguestfs.org/virt-sysprep.1.html): > 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](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest) (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: ```bash 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.