Skip to content

Instantly share code, notes, and snippets.

@taylor8294
Created August 10, 2022 13:52
Show Gist options
  • Select an option

  • Save taylor8294/1ef615b3a050b9b49adf7f2aec120591 to your computer and use it in GitHub Desktop.

Select an option

Save taylor8294/1ef615b3a050b9b49adf7f2aec120591 to your computer and use it in GitHub Desktop.
A guide to setting up an Ubuntu 22.04 Gnome desktop session within WSL2 on a windows machine, including audio support by using VcXsrv and PulseAudio.

Install WSL

Try https://docs.microsoft.com/en-us/windows/wsl/install

wsl --install

Else https://docs.microsoft.com/en-us/windows/wsl/install-manual

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
wget https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
wsl_update_x64.msi
wsl --set-default-version 2

Reboot.

Install Ubuntu 22.04

From https://docs.microsoft.com/en-us/windows/wsl/install-manual

wget -O ubuntu-2204.appx https://aka.ms/wslubuntu2204
Add-AppxPackage .\ubuntu-2204.appx

Once installed, click on the app to begin Ubuntu installer. Go through the steps (language, name, username, password), leave /mnt/ options as-is, also leave /etc/hosts and resolv.conf settings as they are. Click "Reboot now" and you should have your Ubuntu 22.04 shell.

Option 1: Get systemd and snapd working manually using nsenter

In the brand new Ubunutu shell run the following commands to install Microsoft DEB file from https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#2204

sudo apt update
sudo apt full-upgrade -y
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y apt-transport-https
sudo apt-get update
sudo apt-get upgrade -y

Now, follow below steps (from https://forum.snapcraft.io/t/running-snaps-on-wsl2-insiders-only-for-now/13033)

sudo apt-get install -yqq daemonize dbus-user-session fontconfig
sudo nano /usr/sbin/start-systemd-namespace

/usr/sbin/start-systemd-namespace content

#!/bin/bash

SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')
if [ -z "$SYSTEMD_PID" ] || [ "$SYSTEMD_PID" != "1" ]; then
    export PRE_NAMESPACE_PATH="$PATH"
    (set -o posix; set) | \
        grep -v "^BASH" | \
        grep -v "^DIRSTACK=" | \
        grep -v "^EUID=" | \
        grep -v "^GROUPS=" | \
        grep -v "^HOME=" | \
        grep -v "^HOSTNAME=" | \
        grep -v "^HOSTTYPE=" | \
        grep -v "^IFS='.*"$'\n'"'" | \
        grep -v "^LANG=" | \
        grep -v "^LOGNAME=" | \
        grep -v "^MACHTYPE=" | \
        grep -v "^NAME=" | \
        grep -v "^OPTERR=" | \
        grep -v "^OPTIND=" | \
        grep -v "^OSTYPE=" | \
        grep -v "^PIPESTATUS=" | \
        grep -v "^POSIXLY_CORRECT=" | \
        grep -v "^PPID=" | \
        grep -v "^PS1=" | \
        grep -v "^PS4=" | \
        grep -v "^SHELL=" | \
        grep -v "^SHELLOPTS=" | \
        grep -v "^SHLVL=" | \
        grep -v "^SYSTEMD_PID=" | \
        grep -v "^UID=" | \
        grep -v "^USER=" | \
        grep -v "^_=" | \
        cat - > "$HOME/.systemd-env"
    echo "PATH='$PATH'" >> "$HOME/.systemd-env"
    exec sudo /usr/sbin/enter-systemd-namespace "$BASH_EXECUTION_STRING"
fi
if [ -n "$PRE_NAMESPACE_PATH" ]; then
    export PATH="$PRE_NAMESPACE_PATH"
fi
sudo nano /usr/sbin/enter-systemd-namespace

Paste in the following content into /usr/sbin/enter-systemd-namespace, note this has the following changes from the linked forum post

  • Changed /usr/sbin/daemonize to /usr/bin/daemonize in 1 place
  • Changed /usr/bin/nsenter -t "$SYSTEMD_PID" -a to /usr/bin/nsenter -t "$SYSTEMD_PID" -m -p in 2 places
#!/bin/bash

if [ "$UID" != 0 ]; then
    echo "You need to run $0 through sudo"
    exit 1
fi

SYSTEMD_PID="$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')"
if [ -z "$SYSTEMD_PID" ]; then
    /usr/bin/daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
    while [ -z "$SYSTEMD_PID" ]; do
        SYSTEMD_PID="$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')"
    done
fi

if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
    if [ -n "$1" ] && [ "$1" != "bash --login" ] && [ "$1" != "/bin/bash --login" ]; then
        exec /usr/bin/nsenter -t "$SYSTEMD_PID" -m -p \
            /usr/bin/sudo -H -u "$SUDO_USER" \
            /bin/bash -c 'set -a; source "$HOME/.systemd-env"; set +a; exec bash -c '"$(printf "%q" "$@")"
    else
        exec /usr/bin/nsenter -t "$SYSTEMD_PID" -m -p \
            /bin/login -p -f "$SUDO_USER" \
            $(/bin/cat "$HOME/.systemd-env" | grep -v "^PATH=")
    fi
    echo "Existential crisis"
fi

Then

sudo chmod +x /usr/sbin/enter-systemd-namespace
sudo visudo

Add these lines to bottom of visudo file

Defaults        env_keep += WSLPATH
Defaults        env_keep += WSLENV
Defaults        env_keep += WSL_INTEROP
Defaults        env_keep += WSL_DISTRO_NAME
Defaults        env_keep += PRE_NAMESPACE_PATH
%sudo ALL=(ALL) NOPASSWD: /usr/sbin/enter-systemd-namespace

Then

sudo sed -i 2a"# Start or enter a PID namespace in WSL2\nsource /usr/sbin/start-systemd-namespace\n" /etc/bash.bashrc
touch /root/.systemd-env
logout

Back in windows environment

wsl --shutdown
cmd.exe /C setx WSLENV BASH_ENV/u
cmd.exe /C setx BASH_ENV /etc/bash.bashrc
wget -O $env:userprofile/vmlinux-wsl2-snapd https://github.com/diddlesnaps/WSL2-Linux-Kernel/releases/download/linux-msft-snapd-5.10.102.1/vmlinux-wsl2-snapd-x86_64

(There may be a more recent diddlesnaps/WSL2-Linux-Kernel releases than this one [May 2022], check and update URL in the above.) Then

notepad $env:userprofile/.wslconfig

In notepad paste the following content with YOUR_WINDOWS_USER replaced appropriately.

[wsl2]
kernel=C:\\Users\\YOUR_WINDOWS_USER\\vmlinux-wsl2-snapd

Click on the Ubuntu app to open it again. If everything has gone to plan you should get your shell again, but this time /etc/bash.bashrc should have done everything necessary to have systemd and snapd successfully running.

user@domain:~$ snap --version
snap    2.55.5+22.04
snapd   2.55.5+22.04
series  16
ubuntu  22.04
kernel  5.10.102.1-microsoft-snapd+
user@domain:~$ systemctl status
● domain
    State: degraded
     Jobs: 0 queued
   Failed: 6 units
    Since: Tue 2022-06-28 16:11:32 BST; 7min ago
   CGroup: /
           ├─init.scope
           │ └─1 /lib/systemd/systemd --system-unit=basic.target
           └─system.slice
             ├─...

Option 2: use powershell script

https://github.com/diddledani/one-script-wsl2-systemd

git clone https://github.com/diddledani/one-script-wsl2-systemd .
powershell -NonInteractive -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 -NoGPG -distro Ubuntu-22.04

Option 3: others

Alternative options

sudo --shell
apt install lsb-release
wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg
chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpg
cat << EOF > /etc/apt/sources.list.d/wsl-transdebian.list
deb https://arkane-systems.github.io/wsl-transdebian/apt/ $(lsb_release -cs) main
deb-src https://arkane-systems.github.io/wsl-transdebian/apt/ $(lsb_release -cs) main
EOF
apt update
exit
sudo apt update
sudo apt install -y systemd-genie
sudo nano /etc/bash.bashrc
# .bashrc or .profile file...

# Are we in the bottle?
if [[ ! -v INSIDE_GENIE ]]; then
  read -t 3 -q "yn? * Preparing to enter genie bottle (in 3s); abort? "
  echo

  if [[ $yn != "y" ]]; then
    echo "Starting genie:"
    exec /usr/bin/genie -s
  fi
fi

Install & setup VcXsrv in Windows

Downloaded installer from https://sourceforge.net/projects/vcxsrv/. Run it.

Upon opening XLaunch for the first time you must allow all the firewall options (that includes domain, private and public networks) for this to work.

Then go to Control Panel > Windows Firewall > Create new rule > Inbound. Select TCP Port 6000 and allow all. Can name it something like "WSL Xsrv inbound".

Audio

Set PULSE_SERVER environment variable in WSL

export HOST_IP=$(ip route | grep default | awk '{print $3}')
export PULSE_SERVER=tcp:$HOST_IP

On Windows, change pulseaudio's default.pa file as shown below

load-module module-waveout sink_name=output source_name=input record=0
load-module module-native-protocol-tcp auth-ip-acl=0.0.0.0 auth-anonymous=1

and run

pulseaudio.exe --use-pid-file=false -D

See

Install & setup ubuntu-desktop

sudo apt install ubuntu-desktop gnome
gnome-session

With VcXsrv running on windows with native gl off, and ac flag (reduced access control) on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment