Guide

How to reach KVM and QEMU VM consoles remotely with libvirt

On a Linux machine you'd open a QEMU/KVM guest's screen in virt-manager. From a Windows PC, or when the KVM server sits in a cupboard with no screen of its own, you need another way to reach that console: to watch an install, fix a guest whose network is down, or answer a boot prompt.

libvirt can serve each guest's display over VNC, and the RemoteAccessApp app for Windows can open it through an SSH tunnel to the KVM server. Here's how, plus the virsh commands for everything else and what to do about guests that use SPICE.

  • libvirt VNC through SSH
  • Nothing exposed on the network
  • virsh in the same app

Updated · Works on Windows 10 and 11

How it fits together

By default, libvirt makes a guest's VNC display listen only on the KVM server itself, at 127.0.0.1, on port 5900 for the first display, 5901 for the next, and so on. Nothing else on your network can reach it, which is what you want: VNC's own security is weak.

The app's SSH tunnel goes around that safely. It signs in to the KVM server over SSH, then asks the server to connect to the VNC port on its own loopback address, the same as ssh -L would. The VNC tab connects to the tunnel on your own PC, which only listens on your PC's loopback address and closes with the tab.

Open a guest's console

  1. Step 1: Save the KVM server as an SSH host

    On the Connections page of the RemoteAccessApp app, add the KVM server as an SSH host, with a key if you can (see the SSH keys help), and connect once to trust its key.

  2. Step 2: Find the guest's VNC display

    In a terminal on the server, ask libvirt where the guest's display is:

    virsh vncdisplay my-vm

    127.0.0.1:0 means port 5900, :1 means 5901. If you get an error, the guest may use SPICE or have no display; see below. The guest has to be running for it to have a port.

  3. Step 3: Add a VNC host that goes through the server

    Add a VNC host with address 127.0.0.1 and the port from the last step. In its settings, tick Connect through SSH tunnel and pick the KVM server's saved SSH host. The address is as the server sees it, so 127.0.0.1 here means the KVM server, not your PC.

  4. Step 4: Connect

    Open the VNC host and the guest's screen appears in a tab. If the display has a VNC password, the app asks for it. Scale to fit shrinks the screen to the tab, and View only lets you watch without sending keys or clicks.

If the tunnel is refused

If the server answers "administratively prohibited", its SSH server doesn't allow port forwarding. Set AllowTcpForwarding yes in /etc/ssh/sshd_config on the KVM server (or for your user) and restart the SSH service.

Check and change a guest's display

To see what kind of display a guest has, and where it listens:

virsh dumpxml my-vm | grep -A3 '<graphics'

A line like <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> is what you want: a VNC display, a port picked automatically, listening only on the server. If listen is 0.0.0.0, the display is open to your whole network; change it back to 127.0.0.1 with virsh edit and reach it through the tunnel instead.

Ports picked automatically can change when guests start in a different order, so check virsh vncdisplay again if a console shows the wrong guest, or give the guest a fixed port in its <graphics> line.

Guests that use SPICE

Many guests made in virt-manager get a SPICE display. RemoteAccessApp doesn't have a SPICE client, so it can't open those. Your options:

  • Switch the guest to VNC. Run virsh edit my-vm, change <graphics type='spice' to <graphics type='vnc' with listen='127.0.0.1', save, and shut the guest down and start it again. Remove SPICE-only parts such as a SPICE channel if libvirt complains.
  • Use the guest's own remote access. SSH into a Linux guest, or RDP into a Windows guest, once its network is up.
  • Use the serial console. If the guest has a serial console set up, virsh console my-vm in an SSH terminal to the server gives you its text console with no display at all. Press Ctrl+] to leave it.

virsh for everything else

RemoteAccessApp has no buttons for starting or stopping guests, and it doesn't replace virt-manager. In a terminal on the server, virsh does it all:

virsh list --all            # every guest and its state
virsh start my-vm           # start a guest
virsh shutdown my-vm        # ask the guest to shut down
virsh destroy my-vm         # pull the plug (not a delete)
virsh dominfo my-vm         # CPUs, memory, state

Save these in the terminal's Scripts & History panel, and run a check like virsh list --all on several KVM servers at once with Run on hosts…. Click Dashboard on the server's terminal tab for live CPU, memory, disk and network graphs of the host itself. Guest disk images usually live in /var/lib/libvirt/images, and can be copied to another server with a server-to-server copy once the guest is shut down.

If a guest runs RemoteAccessApp itself and is already in your account, you can clone that VM with virt-manager or virt-clone, and each copy joins your account as a new PC with the same settings.

Several consoles at once

Put a few guests' consoles and the server's terminal side by side in split view, with up to eight panes, and save the layout as a workspace. See split view and workspaces. For hosts on other platforms too, see the guide to managing Proxmox, VMware and KVM hosts, and for a desktop on a small board, Raspberry Pi remote access.

Questions, answered

More homelab and virtualization guides

Related