/bottle-imp

A spinoff of genie to supplement WSL's new built-in systemd support.

Primary LanguagePythonOtherNOASSERTION

bottle-imp

ci

A helper for using WSL's native systemd support

bottle-imp is a spinoff of systemd-genie to supplement WSL's new built-in systemd support.

Why is this necessary?

Well, awesome as the native systemd support is, there are some things it doesn't do, and others that it does in notably different ways from genie or other existing systemd solutions. For more information, you can see my migrating from systemd-genie to native WSL systemd article here.

What does it do, exactly?

The following features are provided by bottle-imp (see the above article for more in-depth explanations):

  • Ensures that securityfs (needed for AppArmor and LSMs) and pstorefs (for debugging panics) are mounted.
  • Ensures that the shared memory area filesystem is mounted at /dev/shm and /run/shm, not vice versa.
  • Ensures that the root file system is mounted with shared propagation.
  • Ensures that the bind mount of /tmp/.X11-unix/X0, which makes WSLg work, is restored after systemd clears out /tmp.
  • Ensures that WSL interop is working, even after systemd rebuilds the binfmts.
  • Ensures that the WSLg-created user runtime directory is mounted for the appropriate user, and is not mounted for other users.
  • Makes sure systemd is up and running before proceeding.
  • Keeps the WSL instance running even when you have no active sessions.

and the big one

  • Creates a login session for you, along with a user systemd and a session dbus.

REQUIREMENTS

First, obviously, if you were previously a user of systemd-genie or one of the other systemd solutions, uninstall it before attempting to set up native systemd support or bottle-imp.

It is a good idea to set your systemd default target to multi-user.target before enabling systemd native support. The default graphical.target used by many distributions includes services for the graphical desktop that would take, at minimum, considerable reconfiguration before operating properly under the WSL/WSLg environment.

If you are using a custom kernel for WSL, it should comply with the suggested means of detecting WSL given in microsoft/WSL#423 - i.e., the string "microsoft" should be present in the kernel version string, which can be found in /proc/sys/kernel/osrelease. You can check this by running systemd-detect-virt; it should return "wsl".

Obviously, since native systemd support only works under WSL 2, the same can be said for imp.

Some systemd units were problematic for various reasons under genie, and continue to be so under native support. A list of common problematic units and solutions is available here.

INSTALLATION

If there is a package available for your distribution, this is the recommended method of installing bottle-imp.

Debian

Dependent packages on Debian are libc6 (>= 2.34), python3 (>= 3.7), python3-pip, python3-psutil, systemd (>= 232-25), and systemd-container (>= 232-25). These should all be in the distro and able to be installed automatically.

To install, add the wsl-translinux repository here by following the instructions here:

https://arkane-systems.github.io/wsl-transdebian/

then install bottle-imp using the commands:

sudo apt update
sudo apt install -y bottle-imp

Arch

An Arch package (.zst) for amd64 can be downloaded from the releases, to right. Install it manually, using pacman -U <file>.

Other Distros

If your distribution supports any of the package formats available, you may wish to try downloading the relevant format and giving it a try. This will almost certainly need some tweaking to work properly.

Debian is the "native" distribution for bottle-imp, for which read, "what the author uses". Specifically, Debian bullseye+, with usrmerge installed.

TAR

There is a .tar.gz of a complete bottle-imp install available from the releases, to right. As a last resort, you can try untarring this (it contains every needed file, with the correct permissions, in the correct path from /) onto your system while root. Don't do this unless you're confident you know what you're doing, you're willing to go looking for any resulting issues yourself, and you aren't afraid of accidentally breaking things. You will need to install the dependencies listed above beforehand.

You should use the -p flag when untarring this release to preserve file permissions and the setuid flag on /usr/bin/imp. As some versions of tar(1) always remove the high bits, you should also check the setuid status of /usr/bin/imp after installing.

USAGE

usage: imp [-h] [-V] [-v] [-a USER] (-i | -s | -l | -c ...)

Helper for using WSL systemd native support.

options:
  -h, --help            show this help message and exit
  -V, --version         show program's version number and exit
  -v, --verbose         display verbose progress messages
  -a USER, --as-user USER
                        specify user to run shell or command as (use with -s or -c)

commands:
  -i, --initialize      initialize WSL interop for user sessions and hold WSL open until explicit shutdown
  -s, --shell           open or connect to a systemd user session, and run a shell in it
  -l, --login           open a login prompt for a systemd user session
  -c ..., --command ...
                        open or connect to a systemd user session, and run the specified command within it (preserves working directory)
  -u, --shutdown        shut down systemd and the WSL instance

For more information, see https://github.com/arkane-systems/bottle-imp/

There are four primary commands available in bottle-imp.

imp -i should be run first to set up your WSL instance. It has two effects (apart from waiting for systemd to be ready); it copies the necessary information to ensure that Windows interoperability works inside systemd-managed login sessions and even services, and it starts a lifetime-running process to ensure that the WSL instance does not terminate even when you have no interactive sessions open.

NOTE: For technical reasons, it is not currently possible to separate these functions; you can't have reliable Windows interop without the lifetime-running process.

NOTE 2: The below commands will still work even if you do not run imp -i; however, Windows interop will not function inside systemd-managed sessions, and the WSL instance will idle-terminate as soon as there are no interactive sessions (technically defined as processes that are children of the Microsoft init) running.

imp -s runs your login shell inside a systemd login session; basically, Windows-side, wsl imp -s is your substitute for just wsl to get started, or for the shortcut you get to start a shell in the distro. It follows login semantics, and as such does not preserve the current working directory.

imp -c [command] runs command inside a systemd login session, then exits. It follows sudo semantics, and so does preserve the cwd.

With either of the above, the imp -a [user] option may be used to specify a particular user to start a shell for, or to run a command as, rather than using the currently logged-in user. For example, imp -a bongo -s would start a shell as the user bongo.

imp -l opens a login prompt. This permits you to log in to the WSL distribution via systemd as any user. The login prompt will return when you log out; to terminate the session, press ^] three times within one second. It follows login semantics, and as such does not preserve the current working directory.

imp -u will shut down systemd cleanly and exit the WSL instance. This uses the systemctl poweroff command to simulate a normal Linux system shutting down. It is suggested that this be used before shutting down the Windows machine or force-terminating WSL to ensure a clean shutdown of systemd services.

Shutting down the WSL instance in this way causes it to exit completely. You should wait for the instance to show as stopped before attempting to restart it or execute further commands inside it.

Configuration file

While one is not supplied by default, a configuration file can be created at /etc/imp.ini, with contents similar to the following:

[imp]
dbus-timeout=240
systemd-timeout=240

The *-timeout settings control how long imp will wait for the system dbus socket to be available, and how long, once it is, imp will wait for systemd to enter either the running or degraded state before giving up. Under normal circumstances, there is no need to set either of these, since imp will move immediately to the next state when it is ready. However, if engaged in extensive systemd debugging or if one is using a particularly slow machine, these timeouts can be controlled here.

BUGS

  1. Using imp to create a session is required for the user login session (and its concomitants, such as a user systemd instance and a session dbus) to be created properly. Simply starting a process with wsl (or using a Linux GUI app shortcut) does not do this, although the problem is less serious than with genie, since the process will still be started with systemd as pid 1.

For information about starting Visual Studio Code remote sessions in login sessions, see #19 .

  1. While the Windows Terminal environment variables, WT_SESSION and WT_PROFILE_ID, will be passed through to shell and command prompt invocations of imp, they will not be passed through to login sessions created with imp -l, due to a limitation in machinectl.

  2. imp requires the python package psutil, which due to technical limitations of zipapp can't be wrapped into the imp executable. As such, imp depends on this package for the system python. If you are inside another python environment, imp may fail unless you install the psutil package into this environment also.