KVM Virtualisation on a Hetzner Server

Actually getting the network configured correctly on both the KVM Host (server) and in the KVM Guests for Hetzner's network proved to be quite tricky, so I thought I would write it up here.

Previously, when I used servers at SoYouStart, the process was simply to buy a block of IP addresses, and create a Virtual Mac address for each one in their Control Panel, after which you would configure each guest VM's NIC with the appropriate IP and Virtual Mac address. Hetzner do not offer Virtual Mac addresses, and so instead a static routing approach is required. This is not better or worse in-particular than SoYouStart, it is just different to what I had become accustomed to ;-)

Network Details

I purchased an additional IPv4 address block from Hetzner to use for my VMs: 222.222.222.240/28. This means that the usable IP addresses for the VMs will be from 222.222.222.241 through to 222.222.222.254 inclusive.

We will create a bridged network setup, and each Guest VM will forward its traffic via the host, the following diagram gives a basic outline.

Configuring the KVM Host

If you did not read my previous post, then our server is running Ubuntu 19.04 and we have already installed the KVM Ubuntu packages by running: sudo apt-get -y install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils uvtool.

First, we need to modify the servers network configuration to create the bridge interface. The configuration file is /etc/netplan/01-netcfg.yaml and the out-of-the-box config for my server looks like:

The bridge interface br0 must have the same MAC address as the physical enp4s0 interface, otherwise Hetzner will not route the traffic from the server.

We have added a static routing rule for the br0 interface for the subnet 222.222.222.240/28 that we purchased for our VMs. Without this we will not be able to send IP traffic to our VMs.

To apply the network changes simply run sudo netplan apply. If anything goes horribly wrong and you can no longer SSH to the server, you will need to arrange to use the Hetzner remote physical console (also called a KVM) to fix the network config. Once you have access you can start by copying the backup of the netplan config back into place and running netplan apply.

Next we must enable IP forwarding, so that the traffic from our new subnet is routed via the servers main IP address, to do this run: sysctl -w net.ipv4.conf.all.forwarding=1. However, for this change to be persisted across reboots, we also need to edit the file /etc/sysctl.conf and within there set net.ipv4.ip_forward=1.

Remember that UFW firewall that we enabled in the previous post? We need to instruct it to allow the IP forwarding, otherwise we will not be able to communicate with out VMs via TCP/IP. This is done by running the command: sudo ufw route allow in on br0 out on br0.

Creating a KVM Guest VM

When creating a guest VM, we will use the Ubuntu Cloud images and uvtool.

As part of the VM setup, I want to specify the network settings that will be used by the Operating System within that VM. To do that, I would like to supply a Cloudinit config for netplan, unfortunately the versions of uvtool shipped before Ubuntu 19.10 do not support that. We can however patch our uvtool to support this. This step only needs to be done once:

The guest's network configuration file does not start with the key network:, as it is passed as the --network-config argument to uvtool.

The gateway and route in the above configuration are set to the IP address of our Host (dedicated server). Our host will forward the IP traffic so that its source has the correct MAC address for Hetzner to route it.

Before we use uvtool to create our VM, we want to make sure that we are using the latest Ubuntu Cloud images, so we refresh our images: