libvirt
2 min read
libvirt is a toolkit and daemon for managing virtual machines. It gives one stable API, and one command line tool (virsh), over several hypervisors: mainly QEMU/KVM, but also Xen, LXC, bhyve and others. Most VM tooling on Linux is built on it, from virt-manager to cloud platforms.

libvirt describes everything as XML: a VM is a domain, and there are networks, storage pools with volumes in them, and snapshots. Definitions are kept by the daemon, so a VM survives reboots and can be started automatically.

Setup
Install libvirt with QEMU, and dnsmasq for the default NAT network:

shell
pacman -S libvirt qemu-full dnsmasq
systemctl enable --now libvirtd.socket
usermod -aG libvirt $USER # manage system VMs without root

On NixOS:
nix
virtualisation.libvirtd.enable = true;
programs.virt-manager.enable = true;
users.users.<name>.extraGroups = [ "libvirt" ];

Connections
Every command talks to a hypervisor through a connection URI:

URIMeans
qemu:///systemsystem-wide VMs, managed by the root daemon (usual choice)
qemu:///sessionper-user VMs, running as your user with limited networking
qemu+ssh://user@host/systemVMs on a remote host, over SSH

shell
virsh -c qemu:///system list --all
export LIBVIRT_DEFAULT_URI=qemu:///system # make it the default

Creating a VM
virt-install creates a domain from an installer image:

shell
virt-install \
--name debian \
--memory 2048 --vcpus 2 \
--disk size=20 \
--cdrom debian.iso \
--osinfo debian12 \
--network network=default

virt-install --osinfo list lists the known operating systems.

virsh
Domains
shell
virsh list --all # every VM and its state
virsh start debian
virsh shutdown debian # ask the guest to power off
virsh destroy debian # pull the plug
virsh reboot debian
virsh autostart debian # start with the host
virsh console debian # serial console (leave with Ctrl+])
virsh domifaddr debian # the guest's IP addresses

Definitions
shell
virsh dumpxml debian > debian.xml # export
virsh define debian.xml # import or update
virsh edit debian # edit the XML in $EDITOR
virsh undefine debian --nvram # forget it (keeps the disks)

Snapshots
shell
virsh snapshot-create-as debian clean-install
virsh snapshot-list debian
virsh snapshot-revert debian clean-install
virsh snapshot-delete debian clean-install

Networks and Storage
shell
virsh net-list --all
virsh net-start default
virsh net-autostart default # the NAT network, 192.168.122.0/24

virsh pool-list --all
virsh vol-list default # disk images, in /var/lib/libvirt/images