QuickEmu with subnet-accessible Desktop VMs (Ubuntu 22.04, Rev: 05/18)

This guide details how to install quickemu on a Linux Ubuntu 22.04 server to run desktop VMs (here, we will install both Ubuntu 22.04 Desktop and PopOS 22.04 Desktop) on the same subnet IP range as the host's primary subnet using a network bridge. Those VMs are remotely accessible on the subnet using a SPICE client. This setup will provide VMs directly accessible on the subnet where the Linux server is running. Because we will specify the MAC addresses of those VMs, we can apply reserved DHCP IPs from our router and allow adding and configuring extra services within hardware firewalls, such as the Firewalla (for example, DNS-over-HTTPS).

Apr 4, 2024
Ā 
šŸ’”
Installing quickemu on a Linux Ubuntu 22.04 server to run desktop VMs on the same subnet IPs (on a network bridge) that are remotely accessible using SPICE.
Ā 
Revision: 20240518-0 (init: 20240404)
QEMU is a "generic and open source machine learning emulator and virtualizer" that provides a robust and flexible virtualization (and emulation) backbone. It caters to a wide range of needs, from development to testing across different architectures. QuickEmu focuses on simplifying the QEMU experience, making it easier for users to create and manage virtual machines (VMs) without needing to manage most of the complexity of setup.
This guide details how to install quickemu on a Linux Ubuntu 22.04 server to run desktop VMs (here, we will install both Ubuntu 22.04 Desktop and PopOS 22.04 Desktop) on the same subnet IP range as the host's primary subnet using a network bridge. Those VMs are remotely accessible on the subnet using a SPICE client. This setup will provide VMs directly accessible on the subnet where the Linux server is running. Because we will specify the MAC addresses of those VMs, we can apply reserved DHCP IPs from our router and allow adding and configuring extra services within hardware firewalls, such as the Firewalla (for example, DNS-over-HTTPS).
Ā 

Preamble

How to use this guide

We recommend obtaining the source for this document. Once you have the source file, open it in an editor and perform a find-and-replace for the different values that you will need to customize for your setup. This will allow you to copy/paste directly from the source file.
Values to adjust (in no particular order):
  • eno1, the network interface we will use to set up the bridge network.
  • br0, the device handler for the bridge.
  • 10.0.0.17, the static IP (DHCP reservation) for the Linux host (Ubuntu 22.04 server)
  • d8:9d:67:f4:4a:51, the MAC address of the eno1 device (that will be cloned to the bridge)
  • 10.0.0.1, the router's gateway address.
  • hostuser, the Linux host user.
  • vmuser, the Linux VM user.

QEMU

QEMU (Quick Emulator) is a free, open-source emulator and virtualizer that performs hardware virtualization.
QEMU is a highly versatile and widely used tool in the virtualization space.
  • Compatibility: QEMU can run on a variety of host operating systems, including Linux, Windows, and macOS. It can emulate several CPU architectures, including x86, x86_64 (AMD64/Intel 64), ARM, PowerPC, and more.
  • Modes of Operation: User-mode emulation allows individual programs to run on a foreign CPU architecture. Full system emulation simulates an entire hardware system, including processor and peripherals, which can run a different operating system.
  • Performance: When used on a system with the same CPU architecture as the guest OS, QEMU can utilize KVM (Kernel-based Virtual Machine) to achieve near-native performance by executing guest code directly on the host CPU via hardware virtualization extensions.

QuickEmu

QuickEmu serves as a frontend to simplify QEMUā€™s usage. It's designed to make it quicker and easier to create and run QEMU virtual machines.
QuickEmu automates many configuration and setup processes in creating a VM.
  • Simplified Configuration: QuickEmu uses simple configuration files to define the virtual machine's specifications, making it easier for users to set up a new VM without exploring the many QEMU command-line options.
  • OS Detection and Setup: This feature automatically downloads and configures operating system images (Linux, Windows, and macOS).

Bridge setup

Install the required tools
sudo apt-get install bridge-utils
Our installation was a server installation. We used DHCP on one network interface to obtain a static reserved IP from our router. As such, our /etc/netplan/00-installer-config.yml is currently:
network: ethernets: eno1: dhcp4: true version: 2
eno1 is our primary interface; it gets its reserved IP (here 10.0.0.17) from DHCP. We want to create a bridge onto the same subnet so that we can specify the MAC address of the VMs we will create and continue to use static reservation on our router for created VMs as well. Because we want our bridge interface to use the same MAC address as our eno1 interface (so that any hardware firewall does not classify it as a new device), we will follow the method described in https://bugs.launchpad.net/netplan/+bug/1718607
Our eno1 device has MAC d8:9d:67:f4:4a:51.
We will create a br0 bridge using the IP details of eno1.
First, rename the .yaml file .yaml.old to avoid it being used by netplan: sudo mv /etc/netplan/00-installer-config.yaml{,.old}
Now, let's create a new /etc/netplan/50-cloud-init.yaml file with the following content:
network: version: 2 renderer: networkd ethernets: eno1: match: macaddress: d8:9d:67:f4:4a:51 dhcp4: false dhcp6: false bridges: br0: macaddress: d8:9d:67:f4:4a:51 interfaces: [eno1] addresses: [10.0.0.17/24] routes: - to: default via: 10.0.0.1 metric: 100 on-link: true mtu: 1500 nameservers: addresses: [8.8.8.8] parameters: stp: true forward-delay: 4 dhcp4: no dhcp6: no
With this configuration, we list the MAC address of eno1 and match it in br0, bridge br0 to eno1, and use the interface's known IP for that bridge. We also tell the system that our gateway is 10.0.0.1 and to use Google's DNS (8.8.8.8) when trying to query.
To avoid netplan from printing a WARNING message when apply-ing the configuration, make sure to check that the file's permissions are 600 or sudo chmod 600 /etc/netplan/50-cloud-init.yaml
Before apply-ing it, it is recommended that you have physical access to the host if you are working over SSH, as the connection might drop while the settings are updated.
Apply the configuration using
sudo netplan generate sudo netplan --debug apply
After a few seconds, your prompt should be back, and you can use the ip a command to see that your br0 interface was created and uses the expected IP and MAC.
To get more details about the bridge, run sudo networkctl status br0

QuickEmu

Installation

For more details on QuickEmu and the type of VMs it supports, please see https://github.com/quickemu-project/quickemu.
Install the pre-required packages for the tool to work (including qemu):
sudo apt install qemu bash coreutils ovmf grep jq lsb-base procps python3 genisoimage usbutils util-linux sed spice-client-gtk libtss2-tcti-swtpm0 wget xdg-user-dirs zsync unzip
Add the quickemu Ubuntu repository and install it:
sudo apt-add-repository ppa:flexiondotorg/quickemu sudo apt update sudo apt install quickemu
Next, create a --likely non-existent-- file and directory for qemu to be able to use the created bridge:
sudo mkdir -p /etc/qemu echo "allow br0" | sudo tee /etc/qemu/bridge.conf sudo chmod 755 /etc/qemu/bridge.conf
Also, quickemu needs to allow our non-admin user to use the bridge helper script. Per those extra steps
sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper

Ubuntu 22.04 Desktop on a Ubuntu 22.04 server

We will use quickget to have the tool download the needed installer and create a default configuration file. We will install all VM files in ~/qemu (adapt as needed), with our user directory as /home/hostuser.
cd mkdir qemu cd qemu quickget ubuntu 22.04
This provides us with a ubuntu-22.04 directory where the different disk images (.iso and .qcow2) will end up, and after you run the quickemu tool, you will have a .sh file with the full qemu-system-x86_64 command.
This command also provided us with a pre-filled ubuntu-22.04.conf file, which currently contains:
#!/usr/bin/quickemu --vm guest_os="linux" disk_img="ubuntu-22.04/disk.qcow2" iso="ubuntu-22.04/ubuntu-22.04.4-desktop-amd64.iso"
Let's extend it to specify the number of cores (cpu_cores), RAM, and disk size, have it use our br0 network, and specify the VM's MAC address (qemu MAC addresses must start with 52:54:00).
Because we are using the bridge, the new VM will ask our router for an IP from its DHCP range, and we can perform a static IP reservation later (because we specified the MAC address).
Our final ubuntu-22.04.conf looks as follows:
#!/usr/bin/quickemu --vm guest_os="linux" disk_img="ubuntu-22.04/disk.qcow2" iso="ubuntu-22.04/ubuntu-22.04.4-desktop-amd64.iso" cpu_cores="8" ram="16G" disk_size="128G" network="br0" macaddr="52:54:00:00:01:01"
We reserve 8 CPU cores, 16GB of RAM, and a 128GB disk (the qcow2 disk will increase as data is added to it) using the bridge network with a specific device MAC.
Because we are starting the VM from a server host, we will need to access the guest VM remotely using a Spice remote desktop client.
quickemu --vm ubuntu-22.04.conf --display spice --access remote --spice-port 3001
The output of the command in our case was as follows (some of the values are hardware-specific, and your prompt's output will match your system):
Quickemu 4.9.1 using /usr/bin/qemu-system-x86_64 v7.0.0 - Host: Ubuntu 22.04.4 LTS running Linux 6.5 (host) - CPU: Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz - CPU VM: 2 Socket(s), 4 Core(s), 2 Thread(s), 16G RAM - BOOT: EFI (Linux), OVMF (/usr/share/OVMF/OVMF_CODE.fd), SecureBoot (off). - Disk: ubuntu-22.04/disk.qcow2 (128G) Just created, booting from ubuntu-22.04/ubuntu-22.04.4-desktop-amd64.iso - Boot ISO: ubuntu-22.04/ubuntu-22.04.4-desktop-amd64.iso - Display: SPICE, virtio-gpu, GL (on), VirGL (off) - Sound: intel-hda - ssh: On host: ssh user@localhost -p 22220 - SPICE: On host: spicy --title "ubuntu-22.04" --port 3001 --spice-shared-dir /home/hostuser - WebDAV: On guest: dav://localhost:9843/ - 9P: On guest: sudo mount -t 9p -o trans=virtio,version=9p2000.L,msize=104857600 Public-hostuser ~/hostuser - Network: Bridged (br0) - Monitor: On host: nc -U "ubuntu-22.04/ubuntu-22.04-monitor.socket" or : socat -,echo=0,icanon=0 unix-connect:ubuntu-22.04/ubuntu-22.04-monitor.socket - Serial: On host: nc -U "ubuntu-22.04/ubuntu-22.04-serial.socket" or : socat -,echo=0,icanon=0 unix-connect:ubuntu-22.04/ubuntu-22.04-serial.socket - Process: Starting ubuntu-22.04.conf as ubuntu-22.04 (15406) - Viewer: spicy --title "ubuntu-22.04" --port "3001" --spice-shared-dir "/home/hostuser" "" >/dev/null 2>&1 &
The VM is now started. If you were to do a ps auwwx you would see a long command line defining all the parameters of the qemu command line. Ours starts with /usr/bin/qemu-system-x86_64 -name ubuntu-22.04,process=ubuntu-22.04 -pidfile ubuntu-22.04/ubuntu-22.04.pid and is multiple lines long.
The SPICE access is on the VM host, so 10.0.0.17 using port 3001 as manually specified in the quickemu command line.

macOS access to the VM using SPICE

Please check https://www.spice-space.org/download.html for a list of clients for different OSes.

spice client & ssh access

brew provides us with the spicy-gtk client for installation: brew install spice-gtk
Once installed, you can use spicy -h IP -p port.
The spice port above was 3001, and spice is running on the VM host (not the VM itself, also called the VM guest). To access it, use spicy -h 10.0.0.17 -p 3001
Once you can see the Ubuntu Desktop (VM guest)'s installer running on our Ubuntu server (VM host), perform the installation (you will be able to change the resolution) of your vmuser account.
The Ubuntu VM got its DHCP IP on our router and used an available DHCP range IP, 10.0.0.214. It is on the same subnet as our other hosts and can be reached at this IP directly. Because we know the MAC address (which we specified in the configuration file), we can use the router to specify a reserved IP for future use and extra hardware-firewall-specific features.
Once the Ubuntu Desktop installation is completed, reboot and perform updates on the VM (sudo apt update && sudo apt upgrade), then run sudo apt install openssh-server to install the SSH server.
Because the VM exists on the router's subnet, we can access the VM guest at its IP address directly: ssh [email protected].

aSPICE Pro (alternate spice client)

An alternate client (paid) for SPICE is available in the Mac App Store, named "aSPICE Pro"
For the mouse pointer to work with it, per their documentation, you will need to modify the startup command line slightly:
quickemu --vm ubuntu-22.04.conf --display spice --access remote --spice-port 3001 --extra_args "-device usb-tablet,id=input0"
After creating a host configuration (VM guest name, VM host's IP, SPICE port, and SSH access to the VM host if that is your preferred method), you will be able to access the Desktop of your VM guest.
If you make a mistake or want to edit the host, you can do so by left-mouse long-pressing on the host configuration you wish to edit.

PopOS VM

Similarly to Ubuntu Desktop, you can run other Linux distributions (as well as other OSes) using quickget to obtain the installer and a default configuration file.
Depending on the OS, the command line parameters might vary, and licenses or hardware limitations might occur.
To get the VM installation file for PopOS, we need to specify one more parameter: quickget popos 22.04 intel
Edit the popos-22.04-intel.conf file to adapt it to your preferences, see https://github.com/quickemu-project/quickemu?tab=readme-ov-file#tuning-cpu-cores-ramā€”disks for options.
If you run it on the same br0 network, run it on a different macaddr than other QEMU VMs, for example, "52:54:00:00:01:02".
Finally, start the VM using quickemu --vm popos-22.04-intel.conf --display spice --access remote.
When you close the VM from the Desktop, the process will terminate, and you can restart it using the same quickemu command line.

Troubleshooting

Running alongside Kolla-Ansible-OpenStack

This is not recommended, but should you decide to do so, Kolla-Ansible-OpenStack (KAOS) own --and modify the owner if it gets changed-- the /dev/kvm device, so we need to allow our hostuser to use it.
# If Kolla-Ansible-OpenStack is installed, it owns the /dev/kvm device, figure out the userID ls -ld /dev/kvm # In our case it was 42427 # Add a new kaoshelper user so we can add ourself to its group sudo adduser --no-create-home --uid 42427 --disabled-password --disabled-login kaoshelper # Now the /dev/kvm group will be owned by kaos, add ourselves to that group sudo usermod -a -G 42427 `id -un` # logout and log back in here too, then check your user is in the right group using id

Revision History

  • 20240518-0: Notion migration
  • 20240406-1: title tweak
  • 20240406-0: "user" clarifications + extended text + title change
  • 20240404-0: Intitial release.