Manage libvirt scratch VMs
Use indent/dedent to make the inline templates a bit easier to deal with
Fix a copy and paste error
Mention SSH keys


browse  log 



You can also use your local clone with git send-email.


scratch is a tool for creating and cleaning up throw-away or "scratch" VMs in a libvirt environment.

It aims to require very little of you, while also providing a familiar environment, by using "cloud" VM images from various distros. Currently Debian is supported.


To create a new scratch VM:

$ scratch new IMAGE

Where IMAGE is the name of a supported image from scratch list.

scratch tries to guess as many of its configuration options as possible, for instance it will create a user in the VM matching your $SUDO_USER (or $USER if not using sudo), it will copy the /etc/resolv.conf and SSH public keys from your host machine in to the VM and it will handle automatically assigning static IPs from a pool, without requiring DHCP.

Additional customisation of the created VM is possible, see the output of scratch --help and scratch new --help.

For instance to create a bullseye VM with the hostname test and a 10 gigabyte disk:

$ scratch new -L10G -n test bullseye

By default newly created VMs will be added to your host's /etc/hosts file to make resolving their names easier.


For Debian install required packages:

$ apt install bridge-utils openssh-client genisoimage qemu-utils python3-click python3-guestfs python3-libvirt python3-requests

scratch expects a relatively standard Debian environment:

  • An LVM volume group to place VMs in. By default it expects this will be called $HOSTNAME-vg, e.g. if your PC is called laptop it'll expect a volume group called laptop-vg. Logical volumes will be created like vm-{hostname}-root where hostname is the name you give a VM.
  • A copy of each supported VM image will be cached in ~/.config/scratch/images.
  • A Linux bridge to add created VMs to. By default the bridge br-scratch is used, and an IPv4 subnet is selected automatically pased on your PC's hostname, from the range.
  • How you want to arrange routing / firewalling for your bridge is up to you. Optionally you could use a libvirt managed bridge and pass --dhcp to scratch at VM creation time.

For example assuming your automatic subnet is (find this from the output of scratch new --help), this Debian /etc/network/interfaces fragment will configure the default expected bridge:

auto br-scratch
iface br-scratch inet static
    bridge-ports none
    bridge-stp off
    bridge-waitport 0
    bridge-fd 0

#Specifying defaults

Currently no configuration mechanism exists to change the default behaviours, but an alias or wrapper script could be used to supply frequently configured options.

#Caveats, bugs etc

The rm command will remove any logical volume that matches the expected name, regardless of whether the VM actually exists. Logical volumes created by scatch have a specific tag identifying them, and this should be checked at deletion time but currently isn't.

The way the templates are bundled and rendered in the script is a bit gnarly. There are a lot of edge cases to take care of, so some further refining of the new command will likely take place over time.

Nightly cloud images are used and these are not currently signed. It may be beneficial to migrate to using the less frequently updated images which are signed.