Most popular Linux distributions use systemd as the init system. It is like a Swiss-army knife that controls startup, shutdown, service monitoring, and so much more.
Windows Subsystem for Linux (WSL) dances to its own initialization tune, and distros running on WSL do not use systemd, and do not generally employ a traditional init system.
And that is OK.
Let's take a deep breath. It is easy to try to re-make new software in the image of that with which we are familiar. Often, those of us new to WSL have an "I miss systemd" stage. In fact, there are clever hacks to get systemd sort-of-running on WSL. Eager newcomers may turn to these methods.
Slow down, partner. Let's take a moment to better understand the tool, and work with it, not against it.
You don't need systemd. Not on WSL.
I don't hate systemd. This is not an article about systemd vs openrc vs sysvinit vs runit or other init system. Each are worth exploring if that is your thing. Collect them all!
I believe that two skills in particular will yield more satisfaction with WSL:
- A good understanding of how to launch services directly (unmanaged by an init system).
- Familiarity with running containers.
Choose your WSL distro
If you haven't arrived on a Linux distribution to use with WSL, there are many options.
Use whatever distro you like. I use Fedora, and I highly recommend it. While not available in the Microsoft Store, I do have an article on how to set up Fedora 32 or Fedora 33 on WSL 2.
Feel free to go investigate and come back.
Or, pick from the available distributions in the Microsoft Store.
Or, manually download and install an available distribution.
A prerequisite for all this: enable WSL on Windows.
The goal here is to pick the "vehicle" you want to drive, then proceed with installing and launching the services you desire.
Start a web server without
Once you have a distro with which you are comfortable, you can proceed to discover how to launch your service of choice, without an init system.
As an example, let's run the ever-popular nginx web server in the background, on WSL. Without systemd or any other init system.
Whatever distro you use, you should be able to install nginx using your package manager. Something like
sudo apt install nginx (Ubuntu and Debian) or
dnf install nginx (Fedora) or
apk add nginx (Alpine),
sudo zypper install nginx (OpenSUSE), perhaps.
Now let's launch it with systemd!
$ systemctl start nginx System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down $
I thought that went well.
Yes, WSL is a unicorn. But that needn't stop us.
We can start and stop nginx ourselves. For instance, on Fedora, as an unprivileged user, this works:
It starts in the background. I can then go to http://localhost, in a web browser on Windows and see the default landing page for nginx.
Close the WSL window. Refresh your browser. Yes, it is still running.
Launch another WSL window, and do something like
pgrep nginx. You should see various nginx process IDs, because they are still running.
To stop the server gracefully:
sudo nginx -s quit
Now your browser page will not reload, and there will be no remaining running processes.
Of course, running
wsl --terminate my_distro from Powershell or CMD will also shut down the server. Use
wsl -l to see all the names of WSL distributions you have installed.
Using nginx is just an example. You could do the same thing with Apache, for instance, using
sudo httpd and
sudo httpd -k graceful-stop.
Learn from containers
While containers since docker became popular as immutable images that are not persistent after reloads, and WSL is, in contrast, mutable (retaining any changes you make), it does have some similarities to containers.
A container image, while technically an operating system in its own right, is not usually a full-blown operating system as we commonly think of an OS, with init system, scheduled jobs, etc. Most containers published on Docker Hub do one thing: launch a single command or service. They certainly don't need systemd.
All that to say: learn from these sorts of containers. In fact, looking at the
entrypoint.sh or similar will usually reveal the command used to launch the service. Unsure of how to launch nginx? Take a look at an official nginx Dockerfile, toward the bottom, where
CMD is defined.
Once the command is identified, the default flags used in the container may give clues. Of course something like
nginx -h or
httpd -h will show you a wealth of options.
Actually use containers.
Following the container theme, why not actually use containers to launch the service you desire?
There are a couple options for launching containers in a WSL distro. That is, if you are using WSL version 2. WSL 1 will not work with containers.
My preference is to use Podman.
Podman is pretty much a drop-in replacement for Docker when it comes to running images. It is backed by RedHat and is maturing rapidly. Unsolicited opinion: I notice that Podman adopts leading-edge technologies, such as cgroups v2, fully rootless containers, and Kubernetes pod definitions, sooner than Docker.
The first step in using podman is to install and configure it. This is not hard, but does require a little tender loving care. I have written an article on how to get podman up and running in WSL, and configure it to support rootless containers (containers that can be launched without needing root/superuser access).
Once podman is installed and configured, something like the following should spin up an nginx web server (you could first place an
index.html file in the current working directory):
podman run --name nginx_service -p 8080:80 -v "$PWD":/usr/share/nginx/html:ro -d nginx
Since, in the above, port 80 in the container is mapped to port 8080 on the host, you should be able to go to http://localhost:8080 on Windows and see your
-d flag that tells the container to run "daemonized"; in other words, as a background service. The
--name option is a significant convenience; see why below.
To see running containers:
To stop the service:
podman stop nginx_service
See how that container name is convenient?
To start it again:
podman start nginx_service
To update the underlying image (such as when a new version of nginx is released):
podman pull nginx
If you terminate and restart your WSL session, or reboot Windows entirely, you should be able to
podman start nginx_service and have it up and running again. If you really want it to go away,
podman rm nginx_service should work. Then you would need to re-create it if you want it to be available again.
If you are familiar with Docker, all these commands may seem fairly familiar. Even so, you probably want to get to know the documentation at podman.io and/or use
podman help liberally.
In a nutshell, podman brings the entire ecosystem of container images available from [hub.docker.com], [quay.io], and other repositories. This way, a lot of services are available to you, many of which run in the background without a problem, and without systemd.
Docker also works on WSL 2
While Docker seems to want systemd or other init system to launch the Docker daemon, it is possible to launch that service through other means. Once
dockerd is running, it is then possible to use the
docker command from within WSL 2.
Docker Desktop supports a WSL 2 backend that works quite well.
You may also be interested in a tutorial I wrote on using Docker on WSL 2 without Docker Desktop.
Editorial: what is WSL for?
WSL is Linux, so you can pretty much hack it every which way. Go for it. Servers, games, your favorite Linux Gnome or KDE app.
For what it is worth, though, may I offer my two cents on the use cases best suited for WSL: software development, and Linux command line gymnastics. Data wrangling with Python, web apps with Node, Bash scripts, Ruby utilities, learning C, Rust, editing with Neovim, and so on. Am I being too narrow? Let me know in the comments.
Again, if you use it for something else, and it works well, that is wonderful. My hunch, however, is that if you have long-running services that need to auto-start, or you simply need a full Linux experience and WSL falls short, then you may want to look into a virtual machine (VM) on Windows, using Hyper-V, VirtualBox, or VMware. I believe that if you truly need systemd, then a VM may be the best choice.
Or, better yet, dual-boot (or remove Windows) and boot Linux on your laptop or desktop. Honestly, Linux on the desktop is blissful.
WSL is great for those of us who need Windows as their primary operating system (often for work-related reasons), and also need Linux on the command line.
I hope you can have all the Linux you need, where you need it.
I welcome conversation! How can I improve this article? Feel free to use the comments below.
Top comments (12)
Actually, there is the solution for Debian based distro: systemd-genie. It works perfectly and enables Podman that need systemd to manage cgroups. Indeed, there are many benefits like performance!!! there are no problems except the slightly old Podman version for Ubuntu Groovy.
But it is not good for Fedora that is not Debian derived. Podman doesn't work on Fedora 33 distro without genie at all !
Can you elaborate more about your comment "Podman doesn't work on Fedora 33"? That has not been my experience, as noted here.
Sorry, Podman2 can work on Fedora33. But Podman 3 works much better on Fedora 33 and 34 distro and the most important the ability to support cgroup V2 and work rootless without systemd. Is it possible? The problem of genie for Fedora has been solved and PR's for genie for many other distros have been submitted. Nobody refuses to support genie on any non-Debian distros. So, what is the problem? It works.
From my experience, the WSL networking without a full Linux networking toolset is almost impossible: Network Manager, ResolveCtl, etc, HostnameCtl are much more comfortable tools than various patch scripts invented to make WSL usable.
The last hit is the decision to support systemd-based OCI containers.
Good arguments for systemd (especially systemd-based containers), and for genie.
Are you saying that Podman 3 does not work on your systems without systemd?
Podman 3 supports cgroup2 that closely tayed with systemd and utilized by CRun used in Podman 3 instead of RunC. Thisis the long story. This also scenario that I'm testing (more precisely 3.01). It must enable to use Podman by rootless users. All root scenario work OK. Rootless scenario wors too except one bug in systemd 248 for Fedora 34 that still waiting for correction.
Shortly, I'm very satisfied with genie, all *CLI's, native and well documented Linux configurations and without any scripts that I need to run manually.
OK. It sounds like your experience with Podman 3 and cgroup2 support is very different than my own. For me, Podman 3 works flawlessly without systemd.
But it sounds like you have systemd and Podman 3 working for you, so that is good and you are satisfied. If you want to get Podman 3 working without systemd, though, feel free to ask more questions, or consult my article on the subject. Happy to help!
I still need systemd in WSL: indeed my vanilla Docker CE on CentOS7 distro can be started by simple dockerd and uses fd: Host. But systemd is not only service units. I need logs, service dependencys, etc. which are lost for me.
I aucceeded to run Podman on CentOS8 but Podman networking is far to be sutable for WSL because assumes a "normal" Linux network. Podman also lacks the basic Docker feature - plugin-management to disable network plugins.
Docker desktop simply ignores WSL networking limitations.
Really good points. Thanks for thinking through this! So, users maybe don't need systemd...
Well, for those who still want systemd in WSL2, please refer to this -> github.com/DamionGans/ubuntu-wsl2-...
Doesn't work anymore for recent versions of systemd, thus it is archived :(
Try github.com/arkane-systems/genie instead.
Just put it in bashrc
can you please tell me how do I install Sysvinit in Fedora(WSL)!