Nime

Using Graphical User Interfaces like Cypress' in WSL2

The Window Subsystem for Linux is very powerful. After exploring it for a bit, I wanted to push it even further.

Wouldn’t it be cool to run GUIs natively inside of Linux, on your computer running Windows? 🤯

Prerequisites

Let’s get the obvious one out of the way first: WSL2.

I wrote a guide detailing how to take it from 0 to awesome in a short time. Now, it’s time to turn that dial to 11.

For good measure, update that linux install

Terminal window
sudo apt update
sudo apt upgrade

VcXsrv

You can use something called an X-server to display what is going on in the Linux side of the computer.

For this I used the free program VcXsrc.

The first time you run that program, allow “Public networks, such as those in airports and coffee shops” when the Windows firewall pops up.

To display programs that launch on the WSL side of the machine as seperate windows. I chose the options “Multiple windows” and “Start no client”.

On the page that lets you enable extra settings, be sure to disable access control. By default it only allows the local IP 127.0.0.1. Since WSL has its own IP address, which changes often, allow connections from all clients.

disable access control

Cypress

You can replace this with whatever GUI you would like to run. In my case, it was Cypress, so I made sure to set it up.

After installing Cypress in a project, I added a way to launch it in package.json.

{
"scripts": {
"cy:open": "cypress open"
}
}

There were a bunch of errors greeting me when I tried to run cy:open

initial error image

Luckily, it was a helpful error message that points to a docs page with the solution.

Terminal window
sudo apt install libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2

After installing those packages, trying to run cy:open doesn’t error anymore. It doesn’t do anything else either, only show the Opening Cypress message forever.

stuck on opening then launching Cypress

Bash config

The DISPLAY variable

In order for Linux GUI apps to connect to our X-server, a DISPLAY environment variable has to be set.

In your .bashrc (or .zshrc if you are using ZSH)

Terminal window
# set DISPLAY variable to the IP automatically assigned to WSL2
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0

When you start WSL2, it gets its own IP address. That long command will evaluate to the IP that WSL2 set. The DISPLAY variable has the format <host>:<display>.<screen>.
Both <display> and <screen> are set to 0 here so that line will evaluate to something like export DISPLAY=172.17.224.1:0.0, with the <host> changing to the correct IP.

To confirm this worked, print out the variable you just set in the terminal.

Terminal window
echo $DISPLAY
# 172.17.224.1:0.0

Automatically start dbus

A lot of GUI apps use D-Bus to internally communicate.

In .bashrc (or zshrc), under to previous line, add

Terminal window
sudo /etc/init.d/dbus start &> /dev/null

Grant passwordless access for dbus

We need a soduers file to grant our linux user access to dbus without a password.

To accomplish this, use the visido command.
This best practice will ensure you don’t lock yourself out of the system. The sudoers file doesn’t play around, like the README in /etc/sudoers.d/README will tell you.

Terminal window
sudo visudo -f /etc/sudoers.d/dbus

A Nano editor will launch. Enter the following line, where <your_username> is replaced by -🥁drumroll please🥁- your username.

If you aren’t sure what the name of your linux user is, running whoami in the terminal will tell you.

Terminal window
<your_username> ALL = (root) NOPASSWD: /etc/init.d/dbus

Writing a file in the Nano editor is almost as hard as quitting VIM. Press CTRL+O to save, then press Enter to confirm. Finally, press CTRL+X to close the editor.

Launch your GUI app

Close your terminal and open up a new one in the location you want to open the GUI app.

Open the VcXsrv program in Windows (called XLaunch). Be sure to disable access control.

Launch the program in Linux.

Terminal window
# in the directory I installed Cypress and set up the command to launch it
yarn run cy:open

The Cypress interface