Many VFIO enthusiasts are familiar with the graphical front-end for libvirt called virt-manager. Its capabilities extend further than configuration of a handful of local virtual machines. Of particular interest to those who own at least two computers, is the ability to centrally manage multiple virtual machine hosts. The process is easy if you use ssh keys already and generating some if you don’t, it’s a matter of seconds. Let’s get into it.

In most environments where multiple virtualization hosts exist in a network, managing them individually is cumbersome at best. For this reason, utilizing a tool you might already have installed is a good solution. As is the case for libvirt, virt-manager supports many virtualization technologies such as QEMU/KVM, LXC, bhyve, Xen and more. The overview of what you need to do is the following:

generate ssh keys of the control machine add the keys to the machines that will be controlled (might require making a password for root and temporarily allowing ssh password access) add a new connection to virt-manager for each host

One thing before we dive in, some things I do, might not be needed for your setup. The way I’ll describe, is the most reliable and reproducible across distros. With that out of the way, let’s get started.

Generating the SSH Key Pair

The idea we’ll work with, is a simple 2-computer scenario. The first computer, A (a.localdomain) is the local machine and only needs virt-manager installed. The second computer, B (b.localdomain) is the remote virtual machine host. That should be enough to provide a good example and not become confusing about which computer is which. So, to get started (if you don’t have ssh keys), simply run:

ssh-keygen -t rsa

as your non-root user on computer A to generate a public and a private RSA ssh key pair. The default key storage location, is in the ~/.ssh/ directory.

Copying the Keys to the Remote Hosts

This requires some special attention to avoid leaving security holes in your environment. First, you need to edit /etc/ssh/sshd_config and add:

PermitRootLogin yes

on computer B, the remote host in our example. This is insecure and should be reverted back to its original setting later on. Following that, copy the public ssh key of computer A to computer B using:

ssh-copy-id root@compb.localdomain

The above command is run on computer A as you can tell. Now try to ssh into computer B from computer A as root, you shouldn’t be prompted for a password. If this worked, great, you can revert the change in /etc/ssh/sshd_config back to the default which is

PermitRootLogin prohibit-password

and then move on to the next section.

Accessing Remote Hosts with virt-manager

In this part, the authentication backend is in place and all that’s left is to add the host in virt-manager. Ensure the libvirt daemon is running on computer B, open virt-manager on computer A and set things as shown below:

Of course, you will need to replace compa.localdomain with your remote hosts’s FQDN or IP address. At this point you have a working setup and you can create virtual machines as you would on the local host.

Alternative Setup

There is an alternative and more secure (depending on how you look at it) way of making this work but it comes with some caveats. On a system with the default configuration, libvirt is configured to run as the root user. If you decide to go the way I’m going to describe below, you will need to tweak a couple of things. The /etc/libvirt/qemu.con file is the main change, but the location of your virtual drives and ISOs will probably need adjustments.

First and foremost, libvirt needs to run as a standard user. In /etc/libvirt/qemu.conf, change the following values (substitute user with the name of your non-root user):

user="user" group="kvm"

Following that, add your user to the group kvm as well as the libvirt one:

sudo usermod -a -G kvm,libvirt user

and you should be ready to go, the rest of the procedure is the same but you don’t need to configure ssh for root access. This way, nothing is constantly logged in and operating as root, thus minimizing the attack surface.