2

I installed WSL Ubuntu 20.04 on Windows 10. I also installed VcXsrv (Xlaunch). I use the command as follows to start VcXsrv:

 "C:\Program Files\VcXsrv\vcxsrv.exe" :0 -ac -terminate -lesspointer -multiwindow -clipboard -wgl -dpi auto 

At Ubuntu terminal, I am not able to start terminator. Please help.

$ export DISPLAY=0:0
$ terminator
Unable to init server: Could not connect: Connection refused
Unable to init server: Could not connect: Connection refused
You need to run terminator in an X environment. Make sure $DISPLAY is properly set.

Below is the output of netstat

C:\Windows\system32>netstat -abno|findstr 6000
  TCP    0.0.0.0:6000           0.0.0.0:0              LISTENING       42548
  TCP    127.0.0.1:6000         127.0.0.1:65381        ESTABLISHED     42548
  TCP    127.0.0.1:6000         127.0.0.1:65382        ESTABLISHED     42548
  TCP    127.0.0.1:6000         127.0.0.1:65383        ESTABLISHED     42548
  TCP    127.0.0.1:65381        127.0.0.1:6000         ESTABLISHED     42548
  TCP    127.0.0.1:65382        127.0.0.1:6000         ESTABLISHED     42548
  TCP    127.0.0.1:65383        127.0.0.1:6000         ESTABLISHED     42548
  TCP    [::]:6000              [::]:0                 LISTENING       42548
 Get-NetFirewallApplicationFilter |? { $_.Program -like "*vcxsrv*" } | Get-NetFirewallRule

Name : TCP Query User{81BBD37C-DC9F-4C50-B2C6-A1B58CABD66C}C:\program files\vcxsrv\vcxsrv.exe DisplayName : VcXsrv windows xserver Description : VcXsrv windows xserver DisplayGroup : Group : Enabled : True Profile : Domain Platform : {} Direction : Inbound Action : Allow EdgeTraversalPolicy : DeferToUser LooseSourceMapping : False LocalOnlyMapping : False Owner : PrimaryStatus : OK Status : The rule was parsed successfully from the store. (65536) EnforcementStatus : NotApplicable PolicyStoreSource : PersistentStore PolicyStoreSourceType : Local RemoteDynamicKeywordAddresses :

Name : {14B2C126-9C6A-42CA-B496-62F2D88ED067} DisplayName : VcXsrv windows xserver Description : VcXsrv windows xserver DisplayGroup : Group : Enabled : True Profile : Public Platform : {} Direction : Inbound Action : Block EdgeTraversalPolicy : Block LooseSourceMapping : False LocalOnlyMapping : False Owner : PrimaryStatus : OK Status : The rule was parsed successfully from the store. (65536) EnforcementStatus : NotApplicable PolicyStoreSource : PersistentStore PolicyStoreSourceType : Local RemoteDynamicKeywordAddresses :

Name : UDP Query User{87720067-4851-485C-A9B1-ABE74E6BE131}C:\program files\vcxsrv\vcxsrv.exe DisplayName : VcXsrv windows xserver Description : VcXsrv windows xserver DisplayGroup : Group : Enabled : True Profile : Domain Platform : {} Direction : Inbound Action : Allow EdgeTraversalPolicy : DeferToUser LooseSourceMapping : False LocalOnlyMapping : False Owner : PrimaryStatus : OK Status : The rule was parsed successfully from the store. (65536) EnforcementStatus : NotApplicable PolicyStoreSource : PersistentStore PolicyStoreSourceType : Local RemoteDynamicKeywordAddresses :

Name : {1B4ABAF3-28C3-42F8-8C62-3AE54EFFC97C} DisplayName : VcXsrv windows xserver Description : VcXsrv windows xserver DisplayGroup : Group : Enabled : True Profile : Public Platform : {} Direction : Inbound Action : Block EdgeTraversalPolicy : Block LooseSourceMapping : False LocalOnlyMapping : False Owner : PrimaryStatus : OK Status : The rule was parsed successfully from the store. (65536) EnforcementStatus : NotApplicable PolicyStoreSource : PersistentStore PolicyStoreSourceType : Local RemoteDynamicKeywordAddresses :

Gary
  • 21

1 Answers1

1

I had originally voted to close this as a duplicate of the general How to run GUI apps with Windows Subsystem for Linux question, but the reality is that it's a bit different.

We really don't have a general-purpose, "How do I determine the correct DISPLAY variable for WSL?" question Since we ended up troubleshooting this in the comments, let me go through the various options here in an answer.

First, some "search terms". You may encounter different errors when attempting to run Linux GUI applications in WSL:

  • Error: Unable to open display
  • Error E233: cannot open display
  • Error: (SDL_Init) No available video device (from SDL apps)
  • Error: An OpenGL context could not be created

First, do read How to run GUI apps with Windows Subsystem for Linux. You will need to choose one of those solutions in order to run Linux GUI applications in WSL.

But if you are still having issues, then you may need to take additional steps.

WSL2: Windows 11 with WSLg

If you are using Windows 11 with WSLg (the default WSL option for running Linux GUI apps in Windows 11), then your DISPLAY variable should be set by WSL for you. It should be:

$ echo $DISPLAY
:0

This is the equivalent of DISPLAY=localhost:0, because WSLg runs inside the WSL2 VM, so it is "local" to your WSL session.

The firewall rules should also be set for you automatically.

And you should have:

$ echo $WAYLAND_DISPLAY
wayland-0

For running Wayland applications (the successor to X).

If these variables aren't set properly:

  • Check your startup config files to see if you (or an application you installed) is setting the DISPLAY to something else there.

    Try starting WSL (from PowerShell) without running your Bash startup with:

    wsl ~ -e bash --noprofile --norc
    

    And then check the variables again. If they are correct now, then something in your startup is changing them. You'll need to edit your startup config, find the culprit, and fix it.

  • Are you running a Systemd enablement script? If so, try without it. By default the Systemd environment does not have the DISPLAY (and other built-in WSL variables). Most Systemd-enablement scripts will attempt to handle this, but it may have run into a corner-case that it didn't expect.

WSL1: Windows 10 or 11 with a third-party X server

When using a third-party X server like VcXsrv (as in the original question here) in WSL1, the DISPLAY should again be :0, as with WSLg above.

$ echo $DISPLAY
:0

WSL1 runs in the same network as the Windows host, so VcXsrv (etc.) will be local to WSL1.

No special firewall rules are required when running WSL1 with a third-party Windows X server.

WSL2: Windows 10 or 11 with a third-party X server

This is the most complicated case, and the one covered by the original question. You need at least two things in place to communicate with VcXsrv (etc.) under WSL2:

  • The correct IP address for the DISPLAY variable.
  • Firewall rules to allow access

Both of these are needed because WSL2 runs in a separate network than the Windows host. It runs using a virtual network interface behind a virtual switch that is NAT'd. As a result, localhost:0 (or just :0) refers to the WSL2 network interface, not the Windows host.

In a default WSL2 configuration, the DNS resolver is set (by WSL) to the Windows host, using the IP address of that virtual switch. As a result, you can try several options for determining the correct IP for the DISPLAY:

  • export DISPLAY="$(hostname).local:0"

    This uses mDNS, which has been available in WSL2 for the last few years. See this answer on Stack Overflow for more information. This does require that the default resolver is used.

  • export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0

    This parses the /etc/resolv.conf to obtain the IP address of the Windows host where the resolver is running. Again, this requires that the default WSL2 resolver is in use.

  • export DISPLAY=$(host hostname --long | grep -oP '(\s)\d+(\.\d+){3}' | tail -1 | awk '{ print $NF }' | tr -d '\r')

    If the above two options don't work, then (credit this Ask Ubuntu answer, then this option will attempt to obtain the Windows IP address of the primary network interface. Typically this is a private-network address like 192.168.1.100 or 10.0.1.5.

    If this address is static, you can simply hard-code it, which worked for the OP:

    export DISPLAY=192.168.1.100:0` # Adjust with your actual IP
    

    If it is dynamically assigned and changes frequently, then you can use the above command to attempt to obtain it. However, note that this is much slower than any other method. It takes around 3 seconds on my relatively fast system to complete.

Firewall rules

When using WSL2 with a third-party X server, you'll also need to make sure that the firewall is allowing access from WSL2 to the Windows host.

The first time you attempt a connection to the X server, Windows Defender should display a dialog where you can allow access from Public and/or Private networks. Unfortunately, the WSL2 network is considered "Public" from the Windows host, so you'll need to make sure Public is selected.

Note: In my experience, the dialog often comes up behind other windows, and can be easily missed. If this happens, and that dialog is closed without Allowing the traffic, then a "Deny" rule will likely be put in place.

However, a public "Allow" rule here also means that the firewall will allow traffic on that port on other Public networks (like public wifi networks). This can be a security risk, if you do run the X server when not on your home network.

First, make sure that the rules are in place to allow access, at least. From an administrative PowerShell session:

Get-NetFirewallApplicationFilter |? { $_.Program -like "*vcxsrv*" } | Get-NetFirewallRule

Adjust the -like option for the executable for your X server.

It's probably easiest at this point to look for the DisplayName in the output. Then run Windows Defender Firewall from the Start menu and find the associate rules in Inbound Rules. Make sure that there are "Allow" rules in place for (at least) Public networks.

This answer has gotten a bit long, and adding information on limiting the firewall rule to traffic coming from WSL2 (as opposed other Public networks) is probably a bit out of scope. If someone is interested in how to do this, please post a separate question on that particular topic.

NotTheDr01ds
  • 28,025