When moving from WSL1 to WSL2 many things change; apparently this applies to X11 forwarding as well.
What steps do I need to make in order to use X11 forwarding with WSL
I found a solution that worked for me, following: Set Graphics on WSL2
1. Start ssh service
1.1. Open WSL
1.2. Type: sudo service ssh start
2. Get Windows (WSL net) IP
2.1. Open Powershell
2.2. Type: (ipconfig | Select-String -Pattern 'WSL' -Context 1, 5).Context.PostContext | Select-String -Pattern 'IPv4'
2.3. Get the received IP
3. Set environment variable
3.1. In WSL2 terminal type: export DISPLAY=172.23.64.1:0.0 with the IP of the windows entity (2.3) instead of the place holder
4. Launch Xming
4.1. Open Xlaunch and go with the defaults In Specify parameter settings: Check No Access Control
5. Good luck!
Following link: https://docs.google.com/document/d/1ao3vjbC3lCDc9kvybOT5PbuGhC4_k4g8LCjxX23VX7E
Copied my answer from this github issue.
The idea is to use the ability to communicate over stdio.
ubuntu
is the name of the WSL1 distro with socat installed):mkdir -p /tmp/.X11-unix/
socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d Ubuntu socat - TCP\:localhost\:6000"
Basically this sets up a tunnel from the normal X unix domain socket into the host's port 6000.
Let's assume there is a tcp service running at port 5555 on Windows. In the WSL2 distro, run the following command in the background (ubuntu
is the name of the WSL1 distro with socat installed):
socat TCP-LISTEN:5555,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d ubuntu socat - TCP\:localhost\:5555"
This is simply doing the same thing, but in the opposite direction. You can run the following in your WSL1 distro:
socat TCP-LISTEN:5555,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d ubuntuwsl2 socat - TCP\:localhost\:5555"
On my PC, it can handle up to 150MB/s of data so it's not the fastest but fast enough for most applications.
For some people who allowed only for private networks like me,
It should have stop signs on Windows Defender firewall
Double click it and allow the connection for both
So all the 4 items should be ticked green.
and the above answer from @NicolasBrauer was working for me.
Disable the access control when you XLaunch and
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1
For those who may work with simulation engines such as ROS/Gazebo, Unity and so on, another configuration is needed.
Add these to ~/.bashrc
:
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=0
Be sure to enable both Public Access and Private Access for your X11 server in windows. Also disable any access control your X11 server supports.
If you use VcXSrv uncheck Native opengl. Final config for VcXSrv will be like:
Alternative good X11 servers with less difficulties are X410 and MobaXterm. For some details about this configuration refer here and here.
I used the following bash to set display:
export DISPLAY=$(powershell.exe -c ipconfig | grep -A4 WSL | tail -1 | awk '{ print $NF }' | tr -d '\r'):0
The solution from https://github.com/microsoft/WSL/issues/4793#issuecomment-588321333 uses VcXsrv as the X-server, and it is where I'm getting this answer (slightly edited for readability). Note that the original is being updated by its author, so don't forget to re-check.
To make it work:
- On Windows, with the following, change
E:\VcXsrv
to where your installation is, and save it as xxx.bat in your Windows startup folder, e.g.,C:\Users\Me\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
, and you can make it run when boot if you like:@ECHO OFF REM Start WSL once to create WSL network interface wsl exit REM Find IP for WSL network interface SET WSL_IF_IP= CALL :GetIp "vEthernet (WSL)" WSL_IF_IP ECHO WSL_IF_IP=%WSL_IF_IP% setx "WSL_IF_IP" "%WSL_IF_IP%" setx "WSLENV" "WSL_IF_IP/u" REM Change E:\VcXsrv to your VcXsrv installation folder START /D "E:\VcXsrv" /B vcxsrv.exe -multiwindow -clipboard -nowgl -ac -displayfd 720 GOTO :EOF :GetIp ( aInterface , aIp ) ( SETLOCAL EnableExtensions EnableDelayedExpansion FOR /f "tokens=3 delims=: " %%i IN ('netsh interface ip show address "%~1" ^| findstr IP') DO ( SET RET=%%i ) ) ( ENDLOCAL SET "%~2=%RET%" EXIT /B )
- In WSL, edit ~/.bashrc file to add following lines:
export DISPLAY=$WSL_IF_IP:0 unset LIBGL_ALWAYS_INDIRECT
That's all to make WSL2 work automatically. The idea is to get the private LAN IP of WSL interface on Windows, and use Environment variable to pass it to WSL. WSL then updates this LAN IP to DISPLAY for X-Server connection.
The clipboard works well, too, with this setup. I tested this with a WSL2 install of Ubuntu 20.04 LTS.