How to use GUI apps in WSL2 (forwarding X server)
4 min read
If you have already read some of my WSL related articles, chances are that you are using and/or have discovered the potential of WSL 2. However, you might have experimented problems if tried to launch any graphical application within it.
Nowadays, a third-party app is required to run GUI apps, but Microsoft announced on Build 2020 that adding Linux GUI app native support to WSL is on their roadmap. I currently use VcXsrv Windows X Server for that purpose, and that's the tool I will explain on this post. It's an old open-source tool that updates quite frequently. You can check it on Sourceforge.
Installing and configuring VcXsrv
The first step is to download and run the .exe
installer from Sourceforge. On the installation wizard, be sure to check the Disable access control option. This will save us time, avoiding some permission denied errors.
To be sure that this option is always checked, save the configuration to later launch VcXsrv using that config file.
Setting permissions in Windows Firewall
Once VcXsrv is installed, we need to set the proper permissions on our firewall. Here, I assume you use the default Windows Firewall, but if you use a custom firewall (like a firewall provided by an antivirus), you may need to configure it manually.
When executing VcXsrv for the first time, a Windows Firewall pop-up should appear. Just be sure to give it permissions on both private and public networks.
If the pop-up doesn't appear, or if you gave it the wrong permissions by mistake, you can just change the permissions manually. To do so, open Windows Security
app and go to Firewall & network protection -> Allow an app through firewall
and ensure VcXsrv windows x server has both permissions.
Setting the DISPLAY
env var
The last step is to set the DISPLAY
environment variable on our WSL 2 Linux instance. We need to configure the Windows host's IP address as DISPLAY
(where the VcXsrv X server is running). Also, because WSL 2 network changes on every restart, so the Windows host's IP does too, it's needed to dynamically set this value on WSL2 launch.
We can use one of the following statements to dynamically set the DISPLAY
env var to the correct value.
export DISPLAY="`grep nameserver /etc/resolv.conf | sed 's/nameserver //'`:0"
export DISPLAY="`sed -n 's/nameserver //p' /etc/resolv.conf`:0"
export DISPLAY=$(ip route|awk '/^default/{print $3}'):0.0
If you run one of the above commands on your Linux terminal, then, you should see and local IP address when reading the var value. Just use whatever of the above that works correctly on your machine.
export DISPLAY=....
echo $DISPLAY # Example working output: 192.168.128.1:0.0
Lastly, to ensure the DISPLAY env var is updated on every restart, we should add the chosen export
statement to our ~/.bashrc
file (if you are using bash as your command interpreter) or in ~/.zshrc
(if using zsh instead).
Testing it out
Let's test it! First, ensure the VcXsrv is running. You can check it by looking at the icons on your task bar. You should be able to see the VcXsrv icon if the server is up and running.
If you can't see any icon, just start the server by double-clicking on the config file you saved when installing. It will launch VcXsrv server with the configuration on that file. You can open the file with a text editor, if you want to check the configuration inside.
If you have followed all the above steps, you should be able to execute GUI apps within WSL2 already. Let's try with the x11-apps
, some very low resources and low dependencies apps made for testing X server configurations.
sudo apt install x11-apps
xeyes
xcalc
After executing the above commands, you should see two eyes following your mouse. Congratulations! You have successfully configured your WSL2 instance to run GUI apps.
Now what's next? If you want to know how to write code inside WSL with VS Code and run containerized apps using Docker, I wrote about it too.
Troubleshooting
I particularly had an issue trying to use the default 0.0
display as my X server. Indeed, trying to use 0.0
will make the X server to crash on my Windows machine. It took me a few hours to realize, after searching on Google for a while and trying multiple different fixing options.
If you have the same problem, may you can fix it by using the 1.0
display instead. This is how I set the DISPLAY
value.
export DISPLAY=$(ip route | awk '/default/ { print $3 }'):1.0
And this is my VcXsrv config.xlaunch
config file.
<?xml version="1.0" encoding="UTF-8"?>
<XLaunch WindowMode="MultiWindow" ClientMode="NoClient" LocalClient="False" Display="1" LocalProgram="xcalc" RemoteProgram="xterm" RemotePassword="" PrivateKey="" RemoteHost="" RemoteUser="" XDMCPHost="" XDMCPBroadcast="False" XDMCPIndirect="False" Clipboard="True" ClipboardPrimary="True" ExtraParams="" Wgl="True" DisableAC="True" XDMCPTerminate="False"/>