Windows Server 2019/Windows 10 VM on QEMU/KVM on Ubuntu 18.04

This page documents how to set up Windows Server 2019 under QEMU/KVM on Ubuntu 18.04. I suspect the procedure is identical for Windows 10 and somewhat newer Ubuntu versions.

What you will need:

  • An Ubuntu 18.04 server
  • QEMU/KVM installed on it. This is good documentation: https://help.ubuntu.com/community/KVM/Installation
  • A Windows Server 2019 or Windows 10 ISO. You can download them from Microsoft for free and try them for 180 days. Good enough for a test lab.
  • The virtio driver iso, which you can download here [deeplink].

ISO locations
It is customary to put boot ISOs in /var/lib/libvirt/boot/ and the disk images in /var/lib/libvirt/images. Other places are fine but if you choose to put your disk images in a different location keep in mind you should tell Apparmor about it lest you get bothered with permissions issues.

This document will not describe backing up and restoring of VMs, nor will it explain snapshotting. Both are interesting in their own right and you should learn about them if you haven’t. I wanted to document specifically the process of installing and configuring a Windows Server 2019/Windows 10 guest.

Overview
1. Setting up the network interface
2. Installing the virtual machine
3. Installing drivers and the guest agent
4. Non-related tips

Setting up the network interface
I’m setting up a bridge interface for the VMs to use. By doing this the VMs will show up in my LAN on a regular LAN IP address. My subnet is 192.168.178.0/24. My host’s IP address is 192.168.178.18.

Open the file /etc/netplan/01-netcfg.yaml, or whatever .yaml file is in /etc/netplan.

Mine looked like this:

network:
  version: 2
  renderer: networkd
  ethernets:
    eno1:
      dhcp4: no
      addresses: [192.168.178.18/24]
      gateway4: 192.168.178.1
      nameservers:
        addresses: [192.168.178.1]

Edit the file to look like this:

network:
  version: 2
  renderer: networkd
  ethernets:
    eno1:
      dhcp4: no
      dhcp6: no
  bridges:
    br0:
      interfaces: [eno1]
      dhcp4: no
      addresses: [192.168.178.18/24]
      gateway4: 192.168.178.1
      nameservers:
        addresses: [192.168.178.1]

Be careful when editing this file; it’s easy to lock yourself out. Things to be aware of:

  • netplan is very picky about indentations. You need to get this right.
  • Instead of # netplan apply do netplan try <file>:
root@z230:/etc/netplan# netplan try 01-netcfg.yaml
Do you want to keep these settings?

Press ENTER before the timeout to accept the new configuration

Changes will revert in 120 seconds

If all goes well do

# netplan apply.

You will end up with a physical interface that provides both the host and the VMs access to your LAN.

In case you have a separate network interface for your VMs try this configuration (enp7s0 and enp4s0f1 are both interfaces on my server; I want the VMs to use interface enp4s0f1 and use enp7s0 for management of the host machine itself):

network:
  ethernets:
    enp7s0:
      dhcp4: no
      dhcp6: no
      addresses: [192.168.178.14/24]
      gateway4: 192.168.178.1
      nameservers:
        addresses: [192.168.178.1]

  enp5s0f1:
    dhcp4: no
    version: 2

  bridges:
     br0:
       interfaces: [enp5s0f1]
       dhcp4: no

Installing the VM

# virt-install --name=W2K19 --ram=2048 --cpu host --hvm --vcpus=2 --os-type=windows --os-variant=win10 --disk /var/lib/libvirt/images/W2K19.img,size=40,bus=virtio --disk /var/lib/libvirt/boot/17763.737.190906-2324.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us_1.iso,device=cdrom,bus=ide --disk /var/lib/libvirt/boot/virtio-win-0.1.171.iso,device=cdrom,bus=ide --network bridge=br0 --graphics vnc,listen=0.0.0.0,port=5904 --check all=off

Let me break that down.

First of all, run the command as root or do sudo. The command for installing new VMs is virt-install. Do read its man page.

--name=W2K19

The VM’s name. In KVM terms this is called it’s domain. please note this name is case sensitive.

--ram=2048

The amount of ram in kilobytes

--cpu host

Tells KVM to use the host’s cpu specifications for caching. If you’re planning on using clustering or live migration read up on this part in virt-install’s man page.

--hvm

Do full instead of para virtualisation, if available

--vcpus=2

Give the VM two virtual CPU cores. Again, read the man file for interesting values, like auto.

--os-type=windows

The VM will be optimized for this OS type.

--os-variant=win10

Do

# apt install libosinfo-bin
# osinfo-query os

for a full list of supported OS variants. Pick the closest one.

--disk /var/lib/libvirt/images/W2K19.img,size=40,bus=virtio

Create a disk at this location with this name. I tend to use the .img extension but .qcow2 is also common. The size is in gigabytes. Because we’re using Qemu we’ll be using the virtio bus driver. Note that we will need to install this driver in order to install Windows on the disk.

--disk /var/lib/libvirt/boot/17763.737.190906-2324.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us_1.iso,device=cdrom,bus=ide

We’re connecting the Windows ISO file to a CD ROM device here.

--disk /var/lib/libvirt/boot/virtio-win-0.1.171.iso,device=cdrom,bus=ide

This is the driver CD ROM ISO file. This contains the driver for the drive we’ll be installing Windows on.

--network bridge=br0

Which network interface to install on the VM.

--graphics vnc,listen=0.0.0.0,port=5904

Tell the VM what to do with graphics output. In this case we’ll send it through a VNC interface listening on any address (0.0.0.0) on port 5904. Check the man page for more options. 5900 is VNC’s default port but I’m already running something on that port so I’m specifying a different number.

--check all=off

Do not verify if the CD ROM is already in use by another VM.

Let’s kick off the installation and connect using your favourite VNC client. I used this one.

Connect VNC to your HOST’s IP address followed by the port you specified. The warning is because we didn’t specify a VNC password. That’s ok for now.

The Windows installer will inform you that there are no drives to install on and would like to add a driver?

Choose the virtio scsi driver. In my case the CD ROM ISO was mounted on e:.

Proceed as normal. At one point the installer will reboot and the connection will get lost. Reconnect and continue the installation.

Installing drivers and the guest agent
The guest agent facilitates communication between host and guest. Among other things this will make the VM shutdown gracefully when rebooting or shutting down the host.

After installation shut down the VM and do

# virsh edit W2K19

This will allow you to directly edit the VM’s definition in the form of an XML file. Look up the section and within it add this section:

<channel type="unix">
 <source mode="bind" path="/var/lib/libvirt/qemu/W2K19.agent">
 <target type="virtio" name="org.qemu.guest_agent.0">
 <address type="virtio-serial" controller="0" bus="0" port="1">
</address></target></channel>

The W2K19.agent part (second line) must be unique per server. Again, the path can be anything but if you deviate from this standard you must tell Apparmor about it. I suggest you stick to the path above.

Start the server:

# virsh start W2K19

In the VM start the Device Manager. Note there are two devices that lack drivers. Rightclick them, choose Update driver and have the wizard search e: and subfolders.

One is the virtio Balloon Drivers, which allows for memory thin provisioning. The other is the virto serial driver, which is used by the virtio guest agent to facilitate communication between host and guest.

Shut down the VM and restart it with

# virsh start W2K19

To test agent communication, do

# virsh qemu-agent-command W2K19 '{"execute":"guest-info"}'

This should result in quite a bit of information.

If communication cannot be established your will see “error: argument unsupported: QEMU guest agent is not configured”.

Non-related tips

  • Use tmux, a terminal multiplexer like screen. It allows you to do more than one thing at a time on your terminal and is highly customizable.
  • Use BgInfo to easily see which VM you are managing.
  • Learn about KVM snapshots and backups.

3 Comments

  1. trefmanic

    So, to sum up my two previous comments, this part:
    “Look up the section and within it add this section:”

    should be:
    “Look up the <devices> section and within it add this section:”

    Please remove my previous comments.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.