Before we dive into the technical details, here’s a preview of the result! Notice the little Tux icon in the taskbar indicating that the app is being ran from WSL - neat!
Introduction
I have recently started using Windows again on my personal machine, a Lenovo yoga c930. I was getting frustrated with the issues relating to suspend and the audio under Linux and decided I would give Windows 11 and WSL a try. One of the first things that I wanted to test was WSLg, which gives you the ability to run GUI applications from the linux WSL environment that appear “natively” on Windows. In this article, I’ll detail the steps I took to enable running GUI apps from WSL, and even running a QEMU VM!
Installing WSL and WSLg
WSL
With Windows 11, Microsoft has made it much easier to install WSL. Simply issue
wsl --install
in a powershell session and you are good to go.
Now that you have WSL installed, you need to install whatever distro you will use. You can opt for the ones provided by Microsoft in the Store, or you can download your own. I wanted a roling release distro and went with openSUSE Tumbleweed, following this guide.
I would also recommend installing the Windows Terminal which you can get in the Microsoft Store for free. This will make it easier to access your installed distros from a central place.
WSLg
If you download the official Ubuntu WSL app from the Microsoft Store, WSLg should work out of the box. In my case, this did not work so I followed this guide by Hayden Barnes who also wrote the previous article - thanks Hayden. Make sure you test it out with some simple app like gedit. If this shows up in Windows, you are now setup for running Linux GUI apps from WSL.
Running MicroOS in QEMU
Now that you have your distro installed and WSLg working, let’s install QEMU. The instructions here are for openSUSE, but you can install the necessary packages from your distro’s package manager (apt, dnf, pacman etc..).
$ sudo zypper in qemu qemu-x86 qemu-tools qemu-ui-gtk
Next, you’ll need to pick a disk or image to run our VM from. I opted for the qcow2 disk provided by MicroOS, an immutable OS based on openSUSE Tumbleweed. I also created a copy of it as this is the disk we use to boot our VM and will persist changes (unless you use the -snapshot flag in the qemu-system-x86 command). This means that if anything goes wring, we can start over without having to download the disk file again.
$ mkdir qemu
$ cd qemu
$ wget https://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen.qcow2
$ qemu-img create -f qcow2 -F qcow2 -b openSUSE-MicroOS.x86_64-kvm-and-xen.qcow2 my-microos.qcow2
We are all set for running our QEMU VM, so let’s do it!
$ sudo qemu-system-x86_64 -enable-kvm -drive file=my-microos.qcow2 -m 2G
Unable to init server: Could not connect: Connection refused
gtk initialization failed
Oh… maybe we aren’t so set. The issue here is that WSL uses the DISPLAY
environment variable to tell apps what display to use. This is what we get if we
echo
the variable, so then why is this not working?
$ echo $DISPLAY
:0
Remember that our command is running with sudo, which starts up a new environment as the root user. To get around this, we can do the following:
$ sudo --preserve-env=DISPLAY qemu-system-x86_64 -enable-kvm \
-drive file=openSUSE-MicroOS.x86_64-kvm-and-xen.qcow2 -m 2G
You should now see the QEMU VM running. Once you get to the login prompt, enter the default password. Wait, what default password? Oh you are right, we do not know what that is. We should have read the first line on the download page:
Important: If you don’t install using the DVD, you need to add a SSH key or set a root password using Combustion or Ignition to be able to log in.
I opted for Ignition, which is a project started from Fedora CoreOS. The
quickstart page explains that
we need a config.ign
file in a directory named ignition besides our main disk
image. The Fedora
docs
explain how we can pass the fw_cfg
parameter to our qemu command in order to
do this. So create a directory called ignition and open a file named
config.ign
using your preferred text editor. Paste in the following contents
to set the root user’s password to opensuse1:
{
"ignition": { "version": "3.1.0" },
"passwd": {
"users": [
{
"name": "root",
"passwordHash": "pemFK1OejzrTI"
}
]
}
}
The directory structure should now look something like this:
qemu
├── openSUSE-MicroOS.x86_64-kvm-and-xen.qcow2
├── my-microos.qcow2
└── ignition
└── config.ign
Ok, we are almost there. Let’s remove our qcow disk and copy it over again as Ignition will only apply during first boot.
$ rm my-microos.qcow2
$ qemu-img create -f qcow2 -F qcow2 -b openSUSE-MicroOS.x86_64-kvm-and-xen.qcow2 my-microos.qcow2
We now have the full command to run, which includes the ignition file alongside the disk image:
$ sudo --preserve-env=DISPLAY qemu-system-x86_64 \
-enable-kvm -drive file=my-microos.qcow2 -m 2G \
-fw_cfg name=opt/com.coreos/config,file=ignition/config.ign
Post-boot
One thing that I would recommend doing after the first boot is changing the console font. I opted for Terminus as I know it reads well and comes in a lot of different sizes. MicroOS is an immutable OS, a topic that I will cover in more depth once I get more experienced with it. The basic idea is that the root filesystem is read-only and the system always boots from an image. When installing packages for example, a new image gets created and we need to reboot the machine in order to see the changes. This is great because if anything goes wrong, we can simply boot from the previous working image.
In practice, we need to use a different method to install things. Here I want to
install a font and apply it to the console. We use transactional-update pkg
to
install the package, then set the font 2 and reboot to apply both changes.
$ transactional-update pkg install terminus-bitmap-fonts
$ echo FONT=ter-v28b.psfu > /etc/vconsole.conf
$ systemctl reboot
Conclusion
I hadn’t expected to write such a long article, but I hope it can serve as a reference for my future self and others who might want to try this! It’s great that we have the option to run QEMU VMs under WSL, and the setup is fairly straightforward. It probably would have been easier if I were using a different OS, although we did learn quite a few neat things along the way. You can experiment with any qemu images or architectures that you want to try out. Have fun :)
-
You can do much more with Ignition, but I did not explore it any further. Feel free to go over the documentation in the quickstart if you want to set other things up this way. ↩︎
-
You can see a list of fonts that the console can use under /usr/share/kbd/consolefonts. More reading from the Arch wiki entry ↩︎