QEMU backing files: An introduction
This tutorial provides a brief introduction to QEMU backing files. We
assume that you're already familiar with the basics of QEMU, KVM, and virsh.
A backing file is a read-only base image that a QEMU virtual machine's disk image is linked to. The VM's actual disk (the overlay or delta disk) only stores the differences or changes made relative to the backing file. This creates a parent-child relationship between the images.
Advantages of using backing files
Using a backing file, typically in the qcow2 format, offers significant
advantages for managing VMs:
- Rapid Deployment: Creating a new VM is nearly instantaneous. You only need to create a tiny overlay file that points to the large base image, rather than copying the entire 20-30 GB disk image each time.
- Storage Efficiency: You can run dozens of VMs from a single "golden image" (the backing file). Only the unique changes for each VM consume additional disk space. This dramatically reduces storage requirements.
- Template Integrity: The base image remains untouched and pristine. You can easily destroy a test VM and spin up a new, clean one from the same base in seconds, knowing it's in a perfect state.
Example with Debian, KVM, and virsh
Here's a practical workflow for creating a Debian base image and launching a new VM from it.
1. Install the required tools
For this tutorial we will be using tools like virt-sysprep and
virt-customize which are provided by the libguestfs-tools package. Install
the package if you don't have it.
sudo apt update
sudo apt install libguestfs-tools
2. Create and prepare the backing file ("Golden Image")
First, install a base Debian system as you normally would. Let's say this
results in a disk image named debian12-base.qcow2.
After installation, it's critical to generalize this image using
virt-sysprep. 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.
Warning
virt-sysprep modifies the guest or disk image in place. The guest
must be shut down. If you want to preserve the existing contents of the
guest, you must snapshot, copy or clone the disk first.
cd /var/lib/libvirt/images
virt-sysprep -a debian12-base.qcow2
This debian12-base.qcow2 is now your clean backing file.
Warning
A backing file must be treated as read-only and immutable once an overlay image is linked to it. If you need to update a base image, the correct procedure is to create a new, updated base image and then "rebase" the existing overlay images onto the new backing file.
Modifying or deleting a backing image that is in use will result in data corruption or render the virtual machine unusable. Both actions break the dependency chain that the overlay images rely on to function.
Tip
The SSH service will fail to start because the base image does not have any
SSH host keys (virt-sysprep removed them). We can configure the base
image to generate SSH host keys on the first boot. The perfect tool for
this job is virt-customize, which allows you to modify a virtual
machine's disk image from the host by running commands inside it while it's
offline.
virt-customize -a debian12-base.qcow2 --firstboot-command "dpkg-reconfigure openssh-server"
This ensures that every VM created from this base image has a unique set of SSH host keys.
3. Create a new VM from the backing file
Now, create a new, small overlay image for your new VM, which we'll call
web-server-01. For this we can use qemu-img create:
qemu-img create -b debian12-base.qcow2 -F qcow2 -f qcow2 web-server-01.qcow2
This command creates web-server-01.qcow2, which might only be a few kilobytes
initially.
4. Launch the new VM
You can now use virt-install to create and launch a new VM using this overlay
disk.
virt-install \
--connect qemu:///system \
--import \
--virt-type kvm \
--name "web-server-01" \
--memory "1024" \
--autostart \
--vcpus=1 \
--os-variant=debian12 \
--disk "/var/lib/libvirt/images/web-server-01.qcow2,format=qcow2" \
--network "bridge=br0" \
--noautoconsole \
--hvm
The --import flag tells virt-install that you are providing an existing
disk image rather than performing a new OS installation.