A quick way into a systemd "bottle" for WSL
What does that even mean?
Well, this gives you a way to run systemd as pid 1, with all the trimmings, inside WSL 2. It does this by creating a pid namespace, the eponymous poor-man's-container "bottle", starting up systemd in there, and entering it, and providing some helpful shortcuts to do so.
If you want to try it, please read this entire document first, especially the BUGS section.
For those familiar with or coming here from my first cut (https://randomactsofcoding.wordpress.com/2019/06/13/systemd-on-wsl2/) at attempting to get systemd working, this is the revised one after being schooled on the topic by @therealkenc, over here https://github.com/microsoft/WSL/issues/994 .
You will first need to apt install the dbus, policykit-1 and daemonize packages. You will also need to install .NET Core 2.2 inside WSL, following the instructions here: https://dotnet.microsoft.com/download/linux-package-manager/debian9/runtime-2.2.5
Debian and Ubuntu LTS users can simply install from the wsl-translinux apt repository, here: https://packagecloud.io/arkane-systems/wsl-translinux . Most dependencies will install automatically, but since the .NET Core runtime is in its own repository, you will still need to install it first.
Otherwise, download genie.tar.gz from the releases page, untar it, and copy the files therewithin into /usr/local/bin . Make sure that they are chown root, and that
genie is chmod u+s - i.e., setuid root - and chmod a+rx . The other files, including
genie.dll, do not need to be either setuid or world-readable.
...OR BUILD IT YOURSELF
Or you can build it easily enough if you don't want to trust the binary. You need the dotnet 2.2 SDK. Simply clone the repository and run the included ./build inside the genie subdirectory. The build will be placed into the exec subfolder, and permissions changed appropriately. (You will need to enter your password at the sudo prompt.)
genie: Handles transitions to the "bottle" namespace for systemd under WSL. Usage: genie [options] [command] Options: -v, --verbose <VERBOSE> Display verbose progress messages --version Display version information Commands: -i, --initialize Initialize the bottle (if necessary) only. -s, --shell Initialize the bottle (if necessary), and run a shell in it. -c, --command <COMMAND> Initialize the bottle (if necessary), and run the specified command in it.
So, it has three modes, all of which will set up the bottle and run systemd in it if it isn't already running for simplicity of use.
genie -i will set up the bottle - including changing the WSL hostname by suffixing -wsl, to distinguish it from the Windows host - run systemd, and then exit. This is intended for use if you want services running all the time in the background, or to preinitialize things so you needn't worry about startup time later on, and for this purpose is ideally run from Task Scheduler on logon.
genie -s runs your login shell inside the bottle; basically, Windows-side, wsl genie -s is your substitute for just wsl to get started, or for the shortcut you get to start a shell in the distro.
genie -c [command] runs command inside the bottle, then exits. The return code is the return code of the command.
Once you have this up and running, I suggest disabling via systemctl the getty@tty1 service (since logging on and using WSL is done via ptsen, not ttys).
Personally tested by me:
- Debian 9 (stretch)
- Ubuntu 18.04 (xenial)
- Ubuntu 19.04 (disco)
I have a report of this (mostly) working for Arch, but I also have reports of various odd issues with it not working or not fully working on Arch. I could very much use some help debugging here.
Note that this does not imply that it won't work on other distributions; merely that no-one's tried it and reported it back to me yet. If you do, please do.
This breaks pstree and other /proc-walking tools that count on everything being a child of pid 1, because entering the namespace with a shell or other process leaves that process with a ppid of 0. To the best of my knowledge, I can't set the ppid of a process, and if I'm wrong about that, please send edification and pull requests to be gratefully accepted.
genie -c, in the process of setting the correct gid for the command to run under, drops the user's supplementary groups. Being worked on.
It is considerably clunkier than I'd like it to be, inasmuch as you have to invoke genie every time to get inside the bottle, either manually (replacing, for example, wsl [command] with wsl genie -c [command]), or by using your own shortcut in place of the one WSL gives you for the distro, using which will put you outside the bottle. Pull requests, etc.