Refine Gentoo on Windows Subsystem for Linux

8 minutes to read

This article covers some information that can help perfect a Gentoo installation on Windows Subsystem for Linux (WSL) to maximize its performance, improve its interoperability with Windows, and even unlock new system capabilities.

Originally, I had been planning to write a full Gentoo on WSL installation tutorial during September of the last year, but that tutorial was only halfway done before I had to move on for something more important in my real life, which is why I have disappeared from my personal site for almost another half of year (though you could find my development activities on GitHub if you looked at my profile). Now that I can enjoy a short break with some peace of mind, I have decided to at least complete that tutorial. But before I started, I happened to search for “Gentoo WSL” on Google out of curiosity. While I had been away, there was a new Gentoo in WSL article on Gentoo Wiki originally created on November 24, 2021. That article already covers the bulk of what I wanted to mention in my tutorial in a very concise way, and it is easy to find thanks to the fact that it is on Gentoo Wiki, thus I could no longer see the value of repeating the identical things in lengthy and verbose paragraphs on my personal site.

Despite this, the Gentoo Wiki article does not contain some arcane things with regards to setting up Gentoo on WSL that I would like to share with people. These things might not necessarily make any significant difference, but they can still improve the user experience of certain use cases.

Use WSL Version 2

Although a setup based on WSL 1 is possible, for the best overall experience, please use WSL 2 for Gentoo instead of WSL 1. The main rationale for using WSL 2 is improved file system performance.

Many system administration tasks on Gentoo involve a lot of random file system operations. Before a system upgrade, new and updated ebuilds and metadata cache files need to be synchronized to the system, and it is quite normal for a sync operation to create and write hundreds of new files, if not thousands. When a package is being compiled, a lot of files can be created and copied around the file system too. Using WSL version 2 rather than 1 will help reduce sync time and package build times.

The impact of WSL 1’s inferior file system performance can be shown clearly even during the setup process of Gentoo on WSL. Gentoo stage archives do not contain the ebuilds in the Gentoo repository, so an initial sync of all ebuilds is needed during the setup. As of the initial version of this article is written, there are more than 121,000 files in the Gentoo repository, and downloading every of them to a distribution using WSL 1 would take more than 10 minutes, whereas on WSL 2, this would need only about one minute.

In addition, on WSL 1, Portage can emit scanelf: enabling seccomp failed and Unable to unshare: EACCES warning messages. This is likely to be caused by the fact that WSL 1 does not use a real Linux kernel. On WSL 2, however, Portage and everything else on Gentoo work perfectly just like on a bare-metal Gentoo installation because a real Linux kernel is being used. So, this would be another reason to prefer version 2 to version 1 when setting up Gentoo on WSL.

To use WSL 2, simply include --version 2 at the end of the wsl --import command used to import Gentoo stage3 tarball into WSL:

> wsl --import <Distro> <InstallLocation> <Tarball> --version 2

Windows might emit messages saying that some updates need to be installed or some features need to be enabled. In this case, follow any instructions given in the messages to install or enable them.

Preserve PATH Environment Variable Elements Added by Windows

When configured properly, Windows applications and tools can be launched from WSL with their commands, which usually end with .exe. WSL achieves this by including the elements of Windows’s PATH environment variable in WSL’s PATH environment variable. For example, PATH in Debian downloaded from Microsoft Store consists of the following elements:

$ printenv PATH | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/usr/lib/wsl/lib
/mnt/c/Program Files/WindowsApps/Microsoft.WindowsTerminal_1.11.3471.0_x64__8wekyb3d8bbwe
/mnt/c/Windows/system32
/mnt/c/Windows
/mnt/c/Windows/System32/Wbem
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/
/mnt/c/Users/Leo/AppData/Local/Microsoft/WindowsApps

Note the last several PATH elements that start with /mnt – these are members of Windows’s PATH environment variable. They correspond to Windows paths like C:\Windows\System32, and they are the key factor that allows Windows commands to be called from WSL.

However, Gentoo will overwrite those PATH elements added by WSL by default, which will break Windows commands in WSL:

$ printenv PATH | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/opt/bin
$ ipconfig.exe
-bash: ipconfig.exe: command not found

This can be resolved by patching the sys-apps/baselayout package on the Gentoo installation on WSL. The patch will back up the PATH environment variable set by WSL before Gentoo may overwrite it, then append the backup value to PATH set by Gentoo.

From 3ef3b5bf3c4911502beb2a35121699e5f08ebfc8 Mon Sep 17 00:00:00 2001
From: root <root@NVMe-Fussy.localdomain>
Date: Mon, 23 Aug 2021 20:41:01 -0700
Subject: [PATCH] Honor PATH elements set by WSL

---
 etc/profile | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/etc/profile b/etc/profile
index 2afd51d..46026b4 100644
--- a/etc/profile
+++ b/etc/profile
@@ -4,12 +4,18 @@
 # environment for login shells.
 #
 
+# Back up PATH set by WSL because it might be overwritten by profile.env
+WSLPATH="${PATH}"
+
 # Load environment settings from profile.env, which is created by
 # env-update from the files in /etc/env.d
 if [ -e /etc/profile.env ] ; then
 	. /etc/profile.env
 fi
 
+export PATH="${PATH}:${WSLPATH}"
+unset WSLPATH
+
 # You should override these in your ~/.bashrc (or equivalent) for per-user
 # settings.  For system defaults, you can add a new file in /etc/profile.d/.
 export EDITOR=${EDITOR:-/bin/nano}
-- 
2.31.1

To apply this patch, use Portage’s user patch feature. Add this patch as a user patch, then reinstall the sys-apps/baselayout package. For convenience, the patch can be downloaded directly using this link.

The following commands can be used to add the patch as a user patch and reinstall sys-apps/baselayout with the patch applied:

# mkdir -p /etc/portage/patches/sys-apps/baselayout
# cd /etc/portage/patches/sys-apps/baselayout
# curl -O https://leo3418.github.io/res/posts/2022-02-28-gentoo-wsl-perfection/baselayout-honor-WSL-PATH.patch
# emerge --ask --oneshot sys-apps/baselayout

After that, the PATH environment variable in Gentoo will contain elements added by WSL, and Windows commands can thus be invoked from WSL.

$ printenv PATH | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/opt/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/usr/lib/wsl/lib
/mnt/c/Program Files/WindowsApps/Microsoft.WindowsTerminal_1.11.3471.0_x64__8wekyb3d8bbwe
/mnt/c/Windows/system32
/mnt/c/Windows
/mnt/c/Windows/System32/Wbem
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/
/mnt/c/Users/Leo/AppData/Local/Microsoft/WindowsApps

As a side effect, WSL will also append several duplicate PATH elements that Gentoo already has, including /usr/local/bin, /usr/bin, and so on. Fortunately, in general, duplicate elements in PATH do not cause any functional issues. Having PATH elements added by both Gentoo and WSL is more important because it ensures that both programs installed on Gentoo work normally and Windows commands can be called from WSL.

Readers who are interested in learning more about Portage’s user patch feature are welcome to read another article on this website that discusses it in depth.

Automatically Change to WSL User Home Directory upon Gentoo Launch

Users who have been using any Unix environment outside WSL might have gotten used to the fact that when an instance of the shell is launched, the default initial working directory is the home directory – namely ~. On WSL, however, the initial working directory is the Windows user profile directory %USERPROFILE%, whose path is usually C:\Users\<User Name> (/mnt/c/Users/<User Name> on WSL). This is not the same directory as ~, as ~ still points to the home directory for the Unix user on WSL.

If using ~ as the initial working directory is more preferable, then simply add the following script snippet into ~/.bash_profile. Remember to replace /mnt/c/Users/<User Name> with the actual path to the Windows user profile directory on WSL, such as /mnt/c/Users/Leo.

# ~/.bash_profile

if [[ "${PWD}" == "/mnt/c/Users/<User Name>" ]]; then
    cd
fi

The instructions in this section should be applicable to any other non-Gentoo distribution running on WSL as well.

Start OpenRC upon Gentoo Launch on Windows 11 and Above

Since Windows 11, WSL supports boot settings, which allow a command to be run automatically when a new WSL instance starts. This feature can be used to fire up OpenRC when the Gentoo installation on WSL is launched. OpenRC services, like the OpenSSH daemon, can be started automatically with OpenRC, so this feature essentially also allows automatic launch of services upon WSL start.

To start OpenRC with Gentoo on WSL, add the following contents to /etc/wsl.conf. This will start OpenRC in the default runlevel, which is the suitable runlevel for WSL.

# /etc/wsl.conf

[boot]
command = "/sbin/openrc default"

To make a service start with OpenRC automatically, rc-update add may be used, which adds it to the default runlevel. For example, the following command makes the OpenSSH daemon service start with OpenRC:

# rc-update add sshd

Note that any changes to /etc/wsl.conf do not take effect until the Gentoo installation on WSL restarts. To trigger a restart, run the following command from Windows:

> wsl --shutdown

Then, any daemon processes for services to be started with OpenRC will show up in a few seconds after Gentoo launches.

$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 21:47 ?        00:00:00 /init
root        48     1  0 21:47 ?        00:00:00 /init
root        49    48  0 21:47 ?        00:00:00 /init
leo         51    49  0 21:47 pts/0    00:00:00 -bash
root       689     1  0 21:47 ?        00:00:00 sshd: /usr/sbin/sshd -o PidFile=/run/sshd.pid -f /etc/ssh/sshd_config [listener] 0 of 10-100 startups
leo        780    51  0 21:48 pts/0    00:00:00 ps -ef

For the special case of OpenSSH daemon, it may also be tested by attempting to connect to localhost via SSH.

$ ssh localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:RcHZXSg2QvMxE18VygOGZeJQ7sviL2j+8iPVPKSNFdA.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

To access an OpenSSH daemon running on WSL 2, extra networking setup steps are required.