QEMU/networkd
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-networkd
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
[NetDev]
Name=qemu0
Kind=bridge
# /etc/systemd/network/qemu0.network
[Match]
Name=qemu0
[Network]
Address=172.16.10.1/24
IPForward=yes
IPMasquerade=yes
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
dnsmasq
The VM will be hooked up to the bridge generated above, and you'll need to serve it an IP address:
# /etc/dnsmasq.conf
dhcp-range=172.12.10.1,172.16.10.5,12h
dhcp-host=52:54:00:12:34:56,172.16.10.2
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
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.
Yay!