How to Use WSL2 With A GUI

The Windows Subsystem for Linux is a tool to allow developers to run GNU/Linux environments, in a native hypervisor, in an extremely low-intensity manner. WSL provides many benefits to developers, such as allowing access to the Windows file system, providing the ability to use Linux-exclusive software, tools, and features, and much more.

Typically, WSL is a command-prompt-based utility, which serves most developers’ needs, however, a graphical interface is necessary in some cases – but it is rather complicated to configure. In this tutorial, we will setup a GUI in WSL2, and access it using VNC. No additional software outside WSL (like VcXsrv) is required, except, of course, a VNC Viewer.

Upgrading WSL to WSL2 & Installing Dependencies

The key components we need to install are tigervnc-standalone-server and systemd-genie. For this setup, I will use Ubuntu 18.04 LTS (Bionic Beaver) and install GNOME desktop. Because the key components aren’t tied to Ubuntu or GNOME, you are free to choose your favorite distro and GUI, and it won’t be affected by the installation. Let’s get started – first, we need a working WSL2 installation.
Important note: WSL2 is different than WSL – if you don’t currently have WSL2, you should update before proceeding.
WSL2 Command prompt help menu
First, let’s make sure that we are fully up-to-date and prepared to begin installation:
				
					sudo apt-get update
sudo apt-get dist-upgrade -y 
				
			
If you are installing the GUI on a Debian operating system, you will also need the following:
				
					sudo apt-get install curl wget -y
				
			
Now we’re ready to begin installing the main dependencies!

Installing Components

Ubuntu has a convienient desktop and service component installer called tasksel, but it’s not installed by default, so let’s install it:
				
					sudo apt-get install tasksel -y
				
			
Now that we’ve installed it, let’s run it:
				
					sudo tasksel
				
			

At the package list, select your preferred GUI. I installed Ubuntu Desktop. The installation will take a while, so be patient, and maybe grab a coffee while you wait.

Tasksel Tool Interface

Installing VNC Server

Installing the VNC server is fairly straightforward, requiring a single command:
				
					sudo apt-get install tigervnc-standalone-server -y
				
			

Installing the dotnet-runtime

systemd-genie requires the dotnet-runtime but is not installed automatically. If you are installing on Ubuntu 18.04 (Bionic Beaver), follow the commands below. If you are using a different OS or version, follow this installation. Here are the commands to install dotnet-runtime-5.0 on Ubuntu 18.04:
				
					wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt update
sudo apt install dotnet-runtime-5.0
				
			

Installing systemd-genie

Now we will install systemd-genie which is responsible for turning the basic WSL2 framework into a more complete, comprehensive Linux kernel. This is necessary to run GDM (GNOME Display Manager) and/or LightDM properly, giving the user a full graphic interface experience, including the login page, and related features. Here are the install instructions. As of the publication of this article, the codebase currently supports Ubuntu Focal and Bionic, as well as Debian Buster, Bullseye, Bookworm, and sid. For other distros, you must check how to get the appropriate package for your system. The following commands will install systemd-genie on your system, as long as it is supported:
				
					sudo apt-get install apt-transport-https -y
sudo wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg
sudo chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpg
source /etc/os-release
cat << EOF | sudo tee /etc/apt/sources.list.d/wsl-transdebian.list
deb https://arkane-systems.github.io/wsl-transdebian/apt/ $VERSION_CODENAME main
deb-src https://arkane-systems.github.io/wsl-transdebian/apt/ $VERSION_CODENAME main
EOF
sudo apt-get update
sudo apt-get install systemd-genie -y
				
			
The dependency installation process is finally done.
Part Two

Configure your environment

We’ve now installed the dependencies and requirements needed in order to begin configuring the system to access the GUI.

Creating VNC Server passwords

In this setup, each user has a different VNC password. So you have to configure at least three passwords, one for the current user, other for root, and other for gdm, who whill present the login screen. If you don’t configure the password, you won’t able to access the login screen, or the user’s desktop – you can add as many users as you’d like, but there are three that must be added in order to obtain full functionallity. First, let’s configure the VNC password current user:
				
					vncpasswd
				
			

Next, let’s configure the password for the root user:

				
					sudo -H vncpasswd
				
			

Finally, let’s configure the VNC password for GDM (you need to skip this step if you didn’t install GNOME):

				
					sudo -H -u gdm vncpasswd
				
			

Replacing default X by Xvnc

By default, the display manager calls multiple X instances, one for each user session, including the login screen, all provided by gdm. To change this, we are replacing the Xorg script with a new version which calls Xvnc instead of the classic X/Xorg display service. This IS the real magic we are doing.

First, let’s backup the original Xorg script:

				
					sudo mv /usr/bin/Xorg /usr/bin/Xorg_old
				
			

Then, we create a new Xorg script and copy and paste the bash script into the file:

				
					sudo nano /usr/bin/Xorg_new
				
			
				
					#!/bin/bash
for arg do
  shift
  case $arg in
    # Xvnc doesn't support vtxx argument. So we convert to ttyxx instead
    vt*)
      set -- "$@" "${arg//vt/tty}"
      ;;
    # -keeptty is not supported at all by Xvnc
    -keeptty)
      ;;
    # -novtswitch is not supported at all by Xvnc
    -novtswitch)
      ;;
    # other arguments are kept intact
    *)
      set -- "$@" "$arg"
      ;;
  esac
done

# Here you can change or add options to fit your needs
command=("/usr/bin/Xvnc" "-geometry" "1024x768" "-PasswordFile" "${HOME:-/root}/.vnc/passwd" "$@") 

systemd-cat -t /usr/bin/Xorg echo "Starting Xvnc:" "${command[@]}"

exec "${command[@]}"
				
			
Note the screen resolution – this can be adjusted to fit your needs.
Finally, we set the correct permissions for the file and create a link to it:
				
					sudo chmod 0755 /usr/bin/Xorg_new
sudo ln -sf Xorg_new /usr/bin/Xorg
				
			
Attention: sometimes, system updates replace Xorg link with the original version. Just repeat this step if this happens, and Xvnc will work again as Xorg replacement.

Configure Environment Variables

Next, we need to configure the environment variables that the Xorg server is going to read from the user that executes the genie command. To do this, we are going to modify the .bashrc files of both the main user, which you created during the installation of your WSL OS, as well as the root user.

First, open the file:
				
					nano ~/.bashrc
				
			

Then add the following lines to the bottom of the file:

				
					export XDG_RUNTIME_DIR=/run/user/$UID
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0
sudo /etc/init.d/dbus start &> /dev/null
				
			
IMPORTANT: you must also add the above code lines to the root user’s .bashrc file, do this with the following commands:

Switch to the root user:
				
					sudo su 
				
			
Now, open the .bashrc file as your root user, and append the same three lines you used in the previous step to the file:
				
					export XDG_RUNTIME_DIR=/run/user/$UID
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0
sudo /etc/init.d/dbus start &> /dev/null
				
			
Next, refresh your environment variables:
				
					source ~/.bashrc
				
			

Running systemd-genie

Doing this is like booting Linux again, this time with systemd. Because of systemd, gdm will start automatically and will create a X instance to display the login interface. We changed this process to make it create Xvnc instances, so we can access them. The first instance will listen to port 5900, the second instance will listen to port 5901, and so on. This command will show a “connecting to systemd” message for 180 seconds, before giving you a few errors, and prompting you to log in – log in with the credentials you created at initial installation of the OS.

Attention: if you want to avoid initialization errors that show up upon genie start, or make it start faster, you must check this page.
				
					genie -l 
				
			
Congrats! You’re now logged into your GUI-enabled Linux WSL2 operating system! All that’s left is to connect to your WSL server via VNC! To locate your server’s IP address run the following command:
				
					hostname -I
				
			

Accessing the VNC Screen

After a while (usually around 30 seconds, but it can take more time if you don’t have a SSD, around a minute or so), you can test if it’s working properly. Use your favorite VNC Viewer to connect to your localhost port 5900. Use the VNC password set for user gdm, and you should see the login screen appear. This is the login screen for the actual primary user of the OS, the user that you configured during the initial installation. After logging in, the screen will be blank. This is because a new instance of Xvnc was created for the user desktop, listening to port 5901. Connect to this screen now. The logged user’s desktop must appear. When you log out, the screen at port 5900 will show the login interface again. This applies to GDM (which is the case if you installed Ubuntu Desktop). You can change this behavior by changing the configuration file like this:
				
					sudo nano /etc/gdm3/custom.conf
				
			

Uncomment and edit the following lines:

				
					AutomaticLoginEnable=true
AutomaticLogin=[your username without the brackets]
				
			

Shutting Down

One important thing is: once you start systemd services, you cannot just stop your Linux instance. You must perform a standard Linux shutdown. You can do one of the alternatives below:

Power off option on GUI menu
sudo init 0,
inside the genie bottle genie -u, or outside the genie bottle

After doing that, you can safely shut down your WSL instance, either by wsl --terminate or wsl --shutdown. Not doing the shutdown process may cause damage to your WSL instance, so please be careful and bear that in mind.

Final Word:

Thank you for taking the time to work through this tutorial with me, I greatly appreciate your time and interest in Windows Subsystem for Linux! If you encounter any issues or difficulties please don’t hesitate to contact me, I’d love to hear from you!
Share This :