Opening Ubuntu 20.04 Desktop on WSL2
I installed Ubuntu 20.04 (server/terminal) from the Windows 10 app store, and then after launching the Ubuntu Terminal via WSL2 (Windows Subsystems for Linux) , I installed Ubuntu Desktop and did several steps to try and get a desktop instance of Ubuntu 20.04 launched. In short, the steps involved editing the .bashrc file, installing Xming, and then attempting to open the Ubuntu desktop in Xming with the "startxfce4" command. However, "startxfce4" just doesn't open the desktop for me. I can get programs to open with "grun" and the file explorer to open with "gopen" though, so it is working partially.
Does anyone have any alternative suggestions to how I might get the terminal to open up the full Ubuntu Desktop? Obviously, this wasn't what Windows had in mind with WSL2 so this is kind of a reach, but any input would be helpful. Could I somehow do this from the file explorer or with a program that could opened from "grun" or "gopen"?
Solution 1:
I managed to get the full Ubuntu 20.04 Unity desktop GUI running using
VcXsrv by installing the GNOME Desktop the ubuntu-wsl2-systemd-script and then appending a script to my ~/.bashrc
file.
Initially, Ubuntu is root access only, so create a normal account with sudo privileges;-
sudo adduser username
sudo usermod -aG sudo username
exit
From now on, start WSL using that account.
wsl.exe -d distroname -u username
NOTE:
The ubuntu-wsl2-systemd-script calls systemd using --system-unit=basic.target
and thus does not start the gdm or lightdm service, so edit the enter-systemd-namespace
and start-systemd-namespace
files and change --system-unit=basic.target
to --system-unit=default.target
prior to installation.
# runs only if 1st level shell
if [ $SHLVL = 1 ] &&
[ -d "${srv_path="/mnt/c/Program Files/VcXsrv"}" ] &&
[ -f "${srv_exec="$srv_path"/"${srv_name=vcxsrv.exe}"}" ] &&
[ -d "${sys_path="/mnt/c/Windows/System32"}" ] &&
[ -f "${tasklist="$sys_path"/tasklist.exe}" ] &&
[ -f "${taskkill="$sys_path"/taskkill.exe}" ]; then
# find a Windows Process ID
function find_wpid {
echo $("$tasklist" | grep "$1" | awk '{print $2; exit}')
}
# kill a Windows Process ID
function kill_wpid {
"$taskkill" /PID $1 /F /T >/dev/null
}
# export the Windows %UserProfile% path in Linux Format
export WIN_HOME="$(wslpath "$($sys_path"/cmd.exe" /c "<nul set /p=%UserProfile%" 2>/dev/null)")"
# Find the current WSL2 local IP address
srv_addr="$(ip route | awk '{print $3; exit}')";
# shutdown old instance of VcXsrv if running
if [ "${gfx_wpid=$(find_wpid $srv_name)}" ]; then
kill_wpid $gfx_wpid
unset gfx_wpid
fi
# start a new instance of VcXsrv
"$srv_exec" :0 -ac -wgl -fullscreen -notrayicon -dpms &
# wait for startup success
while [ -z $gfx_wpid ]; do gfx_wpid=$(find_wpid $srv_name); done
# Start Windows Pulse Audio if installed
unset srv_exec srv_name
if [ -f "${srv_exec="$srv_path"/pulse/bin/"${srv_name="pulseaudio.exe"}"}" ]; then
# shutdown old instance of Pulse if running
if [ ${snd_wpid=$(find_wpid $srv_name)} ]; then
kill_wpid $snd_wpid
unset snd_wpid
fi
# delete the expired Pulse config
if [ -d "${snd_conf=$WIN_HOME"/.config/pulse"}" ]; then
rm -r "$snd_conf"
unset snd_conf
fi
# Start a new instance of Pulse
"$srv_exec" --use-pid-file=false --disable-shm=true --exit-idle-time=-1 &
while [ -z $snd_wpid ]; do snd_wpid=$(find_wpid $srv_name); done
export PULSE_SERVER=tcp:"$srv_addr";
fi
# setup Ubuntu Desktop
export DISPLAY="$srv_addr":0;
# setting below: 0 = llvmpipe (faster), 1 = software rasterizer
export LIBGL_ALWAYS_INDIRECT=0
export XDG_CONFIG_HOME=$HOME/.config
export XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
export XDG_SESSION_DESKTOP=ubuntu
export XDG_SESSION_TYPE=x11
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export XDG_SESSION_CLASS=user
export XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
# cleanup expired vars
unset tasklist sys_path srv_path srv_exec srv_name srv_addr
# script stays here until gnome-session logout or failure
gnome-session
# shutdown VcXsrv
if [ $gfx_wpid ]; then
kill_wpid $gfx_wpid
unset gfx_wpid
fi
# shutdown Pulse
if [ $snd_wpid ]; then
kill_wpid $snd_wpid
unset snd_wpid
fi
unset taskkill
# shutdown the shell
exit 0
fi
NOTE:
When all is up and running, go to Ubuntu's Settings -> Privacy -> Screen Lock and turn off the screen lock options. Trying to log back in after a screen lock for some reason results in an infinite loop when asking for your password. If that happens, just shutdown the WSL distro and on next start all is OK again.
Optional Audio Support
Download and unpack mingw64-pulseaudio-13.0.7z. Edit the \mingw\etc\pulse\default.pa
file and replace line 38 containing load-module module-waveout sink_name=output source_name=input
with:
load-module module-waveout sink_name=output source_name=input record=0
load-module module-native-protocol-tcp listen=0.0.0.0 auth-anonymous=1
Save the changes, rename the mingw
folder as pulse
and move it into your C:\Program Files\VcXsrv
folder.
I am unsure if this step is required, however I also installed these apps via...
sudo apt-get install alsa-tools-gui pavumeter pavucontrol
Internet access is not immediately available unless you log out of your WSL2 Ubuntu Desktop and log back in again. This has become handy for me as allows me time to copy across updates from my real Ubuntu to the WSL2 Ubuntu without re-downloading them.
Solution 2:
Older question that got bumped today, but my preferred approach for getting a "full desktop" under WSL is to use xrdp
and then simply run Windows Remote Desktop Connection to enter the desktop manager.
The original question mentions both "Ubuntu Desktop" (assuming Gnome) as well as Xfce, so I'll provide steps for both. Xfce is by far the easier of the two, since it does not require Systemd.
Note that I do not have Pulse Audio running for sound.
Xfce
sudo apt install xrdp xfce4
sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini # So it doesn't interfere with Windows RDP on 3389
In /etc/xrdp/startwm.sh
, comment out the last two lines (that mention Xsession) and add:
#test -x /etc/X11/Xsession && exec /etc/X11/Xsession
#exec /bin/sh /etc/X11/Xsession
exec startxfce4
Start xrdp
with:
sudo service xrdp start
And that's it -- You should be able to connect to your WSL Desktop using the built-in Remote Desktop Connection app. The computer to connect to will be localhost:3390
. Make sure Xorg is selected as the Session type.
Gnome Desktop
The first few steps are nearly identical to those for Xfce.
sudo apt install ubuntu-desktop xrdp
sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini # So it doesn't interfere with Windows RDP on 3389
Create ~/.xsessionrc
with the following:
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktop
export XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xd
Then run:
sudo -b unshare --pid --fork --mount-proc --kill-child sh -c "export container=wsl; mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc; exec /lib/systemd/systemd --system-unit=multi-user.target"
This starts Systemd in a new namespace with its own PID mapping. Inside that namespace, Systemd will be PID1 (as it must, to function) and own all other processes. However, the "real" PID mapping still exists outside that namespace.
Note that this is a "bare minimum" command-line for starting Systemd. It will not have support for, at least:
- Windows Interop (the ability to run Windows
.exe
) - The Windows PATH (which isn't necessary without Windows Interop anyway)
If you want a more full featured Systemd, then there are several package and script options out there if you search. There's even a version in the previous answer here on this question. I would encourage anyone trying them to attempt to understand what they are doing so that you can troubleshoot when something doesn't work as expected.
It's also recommended to disable or mask any Systemd units that you don't need.
Wait a few seconds for Systemd to start up, then:
sudo -E nsenter --all --wd="$PWD" -t $(pgrep -xo systemd) runuser -P -l -w WSL_INTEROP -w WSL_DISTRO_NAME $USER -c "set PATH \"$PATH\"; exec $SHELL"
sudo systemctl start xrdp
As with Xfce4, you should be able to connect to your Gnome Desktop using the built-in Remote Desktop Connection app. The computer to connect to will be localhost:3390
. Make sure Xorg is selected as the Session type.