As I start to get more and more into touch with "the industry", I realise that it's pretty much impossible to just walk in with your laptop and start hacking straight away. Mostly, you'll end up in an environment where they're working with some "solution" X, where X isn't just any ordinary application, but some intrusive monster that will change at least 50% of the configuration that handles the fundamental behaviour of your system.

That is rarely nice.

Luckily, things can be virtualised, and shit doesn't need to be accepted like that. But setting up a proper virtualisation solution (that is not server-grade, like Xen) is a little less trivial. There is VirtualBox, but it's almost become one of those intrusive techs on its own, and not very configuration friendly. It doesn't play nice with KVM either. And it's been oracled.

But fortunately, there is QEMU, which is purely CLI-based, and it integrates with KVM, which is nice. It needs some scripting, though, since no one in their right mind would type a QEMU command manually. But that is usually trivially done in an evening full of cursing and cups of tea.

But then, alas! Networking!


systemd is quite a controversial piece of software. Basically it was written to replace formerly existing init/rc solutions. Then, it also replaced login. And docker. And incorporated udev. And dbus. And an HTTP server. That also serves QR code. For login.

Then, it added network handling. Which is cool. Because network handling is usually a pain in the ass. ifupdown, netcfg/netctl, NetworkManager, Wicd and alike have not just emerged for no reason — but they may not be available on all platforms, or be rather GUI-centric. And mostly they feel more like an overlay to the underlying network commands (ip, dhcpcd), than actual network managers.

At this point, systemd-networkd does quite a good job at handling the network, has a text-based configuration similar to ifupdown, and integrates rather well with the system (I mean … it's basically part of the system). The documentation for systemd-networkd — and for systemd in general — is respectable, and it will work on most systems, given that all noteworthy distributions apart from Gentoo have switched to systemd.

And of course, it can set up bridges:

# /etc/systemd/network/qemu0.netdev

# /etc/systemd/network/qemu0.network



In order to allow QEMU to use qemu0 as the bridge, we will need to add an entry into /etc/qemu/bridge.conf:

allow qemu0

The caveat — and also the cool thing — is on the last two lines in the .network file: sysctl's IP packet forwarding settings (net.ipv4.ip_forward) are ignored and instead handled by systemd-network via net.ipv4.conf.<interface>.forwarding. Took me some time figuring this out. This also allows you to remove that weird /etc/sysctl.d/99-ip_forward.conf.

Also, IPMasquerade replaces iptables/nftables rules for masquerading in this simple case.

# systemctl start systemd-networkd


The VM will be hooked up to the bridge generated above, and you'll need to serve it an IP address:

# /etc/dnsmasq.conf


We know the host's IP address on the qemu0 interface, so we choose an appropriate IP address range for DHCP; and we can anticipate the IP address it will get, since we know the guest's network interface MAC address (see below).

# systemctl start dnsmasq


QEMU is really nice. If you're used to point-and-click and it-just-werks, you might have a tough time, but if you know what you want, it's your best friend on a desktop:

qemu-system-x86_64 -enable-kvm -cpu host -smp 4 \
                   -m 4096 \
                   -net nic,model=virtio,macaddr=52:54:00:12:34:56 \
                   -net bridge,br=qemu0 \
                   -drive file=disk.raw,if=virtio,format=raw

-enable-kvm -cpu host -smp 4 will use KVM (you know, to make the performance bearable), use the host's CPU model, and assign it 4 cores.

-m 4096 will assign the VM 4 GiB of memory.

-net nic,model=virtio,macaddr=52:54:00:12:34:56 will create a new Network Interface Card through the virtio interface and 52:54:00:12:34:56 as MAC address.

-net bridge,br=qemu0 will attach said network interface to the network bridge created above.

-drive file=disk.raw,if=virtio,format=raw will attach the raw disk image disk.raw as a virtual disk device through the virtio interface.

You may want to script this.

With the abovementioned configuration, you should now be able to request an IP address via DHCP from the host, which will act as a gateway with NAT to the guest inside the VM.

Passing -nographic -vnc :0 to QEMU will make the VM run without graphical output and a VNC attached to display :0. With an SSH server on the guest, you now basically have a server, in a local network, on your machine.


read more