Continuing on this foolish path to manage some virtual machines on a remote host with TLS and peer authentication, here I'm going to configure VNC.
The trick here is we're really configuring qemu
not libvirtd
as qemu
itself provides the VNC server. On my Debian system the default configuration
file is /etc/libvirt/qemu.conf
. By default, TLS for VNC is not
enabled.
To listen on all interfaces, use TLS and do peer authentication the following options need to be set.
vnc_listen = "0.0.0.0"
vnc_tls = 1
vnc_tls_x509_verify = 1
The default certificates directories are either the default qemu
certificate
directory.
/etc/pki/qemu/ca-cert.pem
/etc/pki/qemu/server-cert.pem
/etc/pki/qemu/server-key.pem
Or the qemu
VNC certificate directory.
/etc/pki/libvirt-vnc/ca-cert.pem
/etc/pki/libvirt-vnc/server-cert.pem
/etc/pki/libvirt-vnc/server-key.pem
I chose to copy them to the latter.
VNC ports are allocated by qemu
starting a port 5900 by default. I'm going to
assume these are reused when either a domain is destroyed or deleted and
allowed the port range 5900:5910 through the firewall.
I could only find limited documentation about where
virt-manager
or virt-viewer
expects the certificates to be installed for
making VNC connections. I ended up using strace
to see where it was trying to
read them from.
I was a bit surprised to find they actually expect the client certificates in
different paths. Here is where virt-manager
reads certificates.
~/.pki/CA/cacert.pem
~/.pki/libvirt-vnc/clientcert.pem
~/.pki/libvirt-vnc/private/clientkey.pem
And virt-viewer
here, which partially overlaps where libvirt reads its
certificates.
~/.pki/CA/cacert.pem
~/.pki/libvirt/clientcert.pem
~/.pki/libvirt/private/clientkey.pem
After copying the missing certificates we should be ready to go.
To create a new virtual machines with a graphical installer, which is what I wanted to do, I still need to download the installer ISO disk image on the server.
$ wget https://channels.nixos.org/nixos-23.05/latest-nixos-gnome-x86_64-linux.iso -P /var/kvm/installers/
It's now possible to create a new virtual machine with virt-manager
and then
use a graphical installer to install an operating system through a VNC display.
1 2 3 4 5 6
I can also script the virtual machine creation with virt-install
which will
launch the virt-viewer
VNC client. A list of possible --os-variant
values
can be found run running virt-install --osinfo list
.
$ virt-install \
--connect 'qemu+tls://hypervisor.tarnbarford.net:16514/system' \
--name demo \
--memory 2048 \
--vcpus 2 \
--disk size=20 \
--cdrom /var/kvm/installers/latest-nixos-gnome-x86_64-linux.iso \
--boot cdrom,hd \
--os-variant nixos-22.05 \
--graphics vnc
Starting install...
Allocating 'demo.qcow2' | 3.1 MB 00:00:03 ...
Creating domain... | 0 B 00:00:00
Running graphical console command: virt-viewer --connect qemu+tls://hypervisor.tarnbarford.net:16514/system --wait demo
Bam! A virt-viewer
window appears displying the install media boot screen.
This is pretty great, I can now quickly and easily create new virtual machines on the server and immediately connect to their display and input devices using VPN client.
I'm still not fully satisfied, when I create virtual machines on my laptop I always prefer SPICE over VPN. The main reason is that SPICE has a feature "Redirect USB device" which works really well for many of my workflows that rely on my USB security key. The reason I didn't setup SPICE initially is that it doesn't support TLS peer authentication (!). I have an idea how I could make this work which I'd like to try, but I'll leave that for another time.