Setting up wake-on-LAN for libvirt virtual machines in Ubuntu 20.04.3

How to setup up wake-on-LAN ("WOL") for libvirt virtual machines on a Ubuntu 20.04 host.

I've never actually had a use case for wake-on-LAN, but I've recently realized that I could configure the server connection in Guacamole to send a wake-on-LAN packet to the server in order to wake it up if it is powered off. I don't know why it took me so long to realize how useful this would be for connecting to resources from within Guacamole, since now I would no longer have to manually start up different virtual machines that I wanted to connect to from within Guacamole.

Setting up wake-on-LAN for bare metal machines is easy enough, but I found out that doing it for libvirt virtual machines isn't as easy because you can't just enable it in the BIOS and the network adapter configurations, since the virtio adapter doesn't have such configuration available.

Hopefully this will help you in setting up your environment so you can use wake-on-LAN to power on your libvirt virtual machines.

After some time Googling, a lot of the solutions to this problem work by running a daemon that listens for wake-on-LAN packets, and then they locate the libvirt virtual machine that has the MAC address that the wake-on-LAN packet was for, then they power on the virtual machine.

The only solution I actually tried was virtwold, so that is the solution this walk through will cover. This was all done on Ubuntu 20.04.3 LTS using libvirtd 7.6.0.

Requirements

  • Go
  • libpcap
  • libvirtd daemon configured to allow the /var/run/libvirt/libvirt-sock socket

Install Requirements

We won't cover how to configure the libvirtd daemon, but you will need to install Go and libpcap.

sudo apt-get install golang-go libpcap-dev

Download virtwold

Download or clone the virtwold repository from https://github.com/ScottESanDiego/virtwold

git clone https://github.com/ScottESanDiego/virtwold

Build virtwold

Create an executable binary of virtwold by using go build.

cd virtwold
go build

This will create a new binary in that directory called virtwold.

"Install" virtwold

You can run the daemon manually each time or create some other startup script, but we will create a systemd service using the provided template.

You need to copy the virtwold binary to a location on your system, by default we will copy it to /usr/local/bin/virtwold.

sudo cp virtwold /usr/local/bin/virtwold

Create systemd service

You'll likely want this daemon to start a service on your system, and virtwold comes with a template of the systemd service you should create. This systemd service lets you start multiple copies of the daemon and lets you control which network interface that daemon will listen to. You do this by specifying the interface name when you enable the service, like so: systemctl enable --now virtwold@br1

Copy the file init-scripts/systemd/[email protected] to /etc/systemd/system/[email protected]

sudo cp init-scripts/systemd/[email protected] /etc/systemd/system/[email protected]

Edit [email protected] (Optional)

If you copied the virtwold binary to a location other than /usr/local/bin/virtwold, then you will need to edit /etc/systemd/system/[email protected] to point the ExecStart configuration to the new path.

sudo nano /etc/systemd/system/[email protected]

Change the ExecStart path to the location of virtwold:

; You'll want to update the path here to where you place the final compiled binary
ExecStart=/usr/local/bin/virtwold -interface %i

Identifying your network interface

In order to enable the service, you will need to tell it which network interface you wish it to listen on. You might already know which network interface, but you can use the commands below to easily list your network interfaces.

ip -o link show | awk -F': ' '{print $2}'

Once you have the network interface you will set the service to listen on, you can enable the service with that interface name. You will want to use the network interface that the virtual network your virtual machines are using is attached to.

Enabling [email protected]

You will need to enable the virtwold service for the specific network interface you wish it to listen on, in our case this will be for the interface br0. This will enable and start the service.

sudo systemctl enable --now virtwold@br0

If you run into issues starting the service, you should view the systemd log

sudo journalctl -u virtwold@br0