You may not need systemd on WSL

Jonathan Bowman Created: September 10, 2020 Updated: June 26, 2023 [Linux] #wsl #windows #linux #systemd To systemd or not to systemd...

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.

In late 2022 Microsoft announced systemd support in WSL.

Prior to that point, however, Windows Subsystem for Linux (WSL) danced to its own initialization tune, and distros running on WSL did not use systemd, and did not generally employ a traditional init system.

This taught folks like me something: I don’t always need to have systemd or other init system for a good Linux experience. Running WSL without systemd is OK.

Of course, if you want to run systemd on WSL, you are not alone, and there are good reasons for doing so: you want to install snaps, for instance, or run Docker easily. Go ahead and use the current version of Ubuntu, or follow Microsoft’s instructions and enjoy yourself.

But if you find yourself in a position where you see advantages in using WSL without systemd, read on.

First, take a deep breath. Let’s take a moment to better understand a simple WSL installation, and work with it, not against it.

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 without systemd:

  1. A good understanding of how to launch services directly (unmanaged by an init system).
  2. 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 one of the standard distros available for free in the Microsoft Store, I do have an article on how to set up Fedora on WSL 2.

Fedora on WSL article

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 systemctl start

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.

nginx

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:

sudo nginx

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

Shipping 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 Dockerfile or 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

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).

Configure Podman on WSL

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 index.html served.

Note the -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:

podman ps

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 know 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.

Rancher Desktop is an alternative to Docker Desktop that offers flexibility and openness many will appreciate. On Windows, it has a great WSL 2 backend.

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? Feel free to let me know.

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.

Back to top