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 aretigervnc-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.
First, let’s make sure that we are fully up-to-date and prepared to begin installation:
sudo apt-get updatesudo 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.
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.debsudo dpkg -i packages-microsoft-prod.debsudo apt updatesudo 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 -ysudo wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpgsudo chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpgsource /etc/os-releasecat << EOF | sudo tee /etc/apt/sources.list.d/wsl-transdebian.listdeb https://arkane-systems.github.io/wsl-transdebian/apt/ $VERSION_CODENAME maindeb-src https://arkane-systems.github.io/wsl-transdebian/apt/ $VERSION_CODENAME mainEOFsudo apt-get updatesudo 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/bashfor 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" ;; esacdone# Here you can change or add options to fit your needscommand=("/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_newsudo 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/$UIDexport DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0sudo /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/$UIDexport DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0sudo /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=trueAutomaticLogin=[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 menusudo init 0
,
inside the genie bottlegenie -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 :