Skip to content
WSLDeep Dive Published Updated 7 min readViews unavailable

The WSL Distribution Boot Command: A Root Hook With a Narrow Contract

Use the per-distro WSL boot command for a small idempotent startup task, and understand its root context, lifecycle, and systemd boundaries.

The [boot] command key in /etc/wsl.conf is a small but powerful WSL integration point: WSL runs the configured command as root when that distribution instance starts. It can remove one manual setup step, but it is not a general-purpose service manager, a Windows scheduled task, or an always-on guarantee. A command that runs on every start must be bounded, idempotent, safe to retry, and useful even when no interactive user is present. Treating it as a root startup hook rather than a convenient shell profile prevents fragile boot sequences and difficult-to-diagnose failures.

Scope and platform requirements

/etc/wsl.conf is stored inside one distribution and applies to that distribution, unlike %UserProfile%\\.wslconfig, which configures global WSL 2 VM behavior. The current Microsoft configuration reference documents the [boot] section for Windows 11 and Windows Server 2022. It lists command as a string, defaulting to null, and specifies that the command runs as root. Check the installed WSL version and host build before relying on a configuration feature copied from a current Windows machine.

The hook runs when the WSL instance starts, not each time a shell opens. That is a different lifecycle from .bashrc, a login shell, a systemd user unit, or a Windows logon task. WSL distributions can stop and start as the user opens tools, shuts down WSL, restarts Windows, or applies an update. command therefore cannot make a service permanently available; it only defines work at a distro startup boundary.

Microsoft’s documentation gives service docker start as an example, but the correct mechanism depends on what the distribution actually runs. If the distro uses systemd and a service has a proper unit, enabling and managing the unit with systemd may express dependencies, restart policy, and logging more clearly. If the task is a single lightweight compatibility action that must happen before a normal user session, the WSL hook can be appropriate. Avoid managing the same service through both command and a systemd unit.

Start with a minimal and idempotent operation

Use a fixed executable or a short wrapper script rather than a large inline command with quoting, shell interpolation, and multiple side effects. For example, an administrator might configure a distribution-local script:

# /etc/wsl.conf
[boot]
command=/usr/local/sbin/wsl-startup-check

The script should be owned by root and should return a useful status. A shell wrapper can be written as:

#!/bin/sh
set -eu

# Example: create a runtime directory only if it is absent.
install -d -o developer -g developer -m 0750 /run/example-app

This example is not a universal service recipe. Confirm that the developer account and group exist in the target distribution, and choose a runtime path whose lifecycle is intentionally temporary. The task should be safe if WSL executes it on every new instance start. Avoid appending an unbounded line to a file, recreating users, regenerating credentials, or running an unconditional package upgrade from the boot hook.

If a hook must start a daemon, call the supported service manager or the daemon’s documented command and make failure visible. Do not background a complex shell pipeline that immediately discards its exit status. A detached process can outlive the short launch command in ways that are hard to observe, and command itself does not provide systemd’s unit dependency graph, restart policy, or journal integration.

Make the operation observable

For a short and intentionally simple hook, record a bounded status to the system journal if systemd is available or to a dedicated log path with rotation. Never send diagnostics to an uncontrolled file under /tmp and assume it will be preserved. Do not include passwords, access tokens, proxy credentials, private key material, or command-line secrets in logs.

On a systemd-enabled distro, determine whether the task belongs in a unit instead. journalctl -b can help correlate service activity to the current boot. When using the WSL hook, the exact logging destination depends on the script and distribution utilities; the configuration key does not magically capture every child process’s stdout and stderr into a durable log. If reliable log collection is a requirement, explicitly redirect output to a managed destination or use systemd, and document retention.

A failed hook may present as a startup symptom even when the Linux kernel and distribution filesystem are healthy. Keep the command short so a person can enter a normal shell and inspect it. If an invalid /etc/wsl.conf or a broken startup command blocks ordinary access, use the documented WSL safe-mode or debug-shell recovery path rather than deleting the distro.

Test the lifecycle rather than just parsing the file

After editing /etc/wsl.conf, stop the specific distro or the shared WSL VM and start it again. A controlled test can use:

wsl.exe --list --running
wsl.exe --terminate Ubuntu
wsl.exe --distribution Ubuntu --exec /bin/true

The setting is distribution-specific, so --terminate Ubuntu is narrower than wsl --shutdown. However, other running distributions can keep the common WSL 2 VM active; when the test specifically needs a fresh VM boot, stop stateful workloads in all distros and deliberately use wsl --shutdown. This command ends every running distro session, so it is not a harmless refresh on a machine hosting active local services.

Test at least four cases: first start after a true stop; a second stop-and-start cycle; an ordinary interactive shell opened while the instance is already active; and a failure path such as a missing optional dependency. Verify that the action occurs once per new instance start, not every shell. Check the resulting filesystem state and service health independently of the wsl.exe process exit code. A successful shell launch does not prove the service is ready.

If startup duration matters, measure it before and after the hook with the same distro, same command, and comparable host load. A network-dependent startup task can add latency or hang while waiting for connectivity. Add an explicit timeout and failure handling to the wrapper instead of allowing a service or mount to block distribution startup indefinitely. A startup hook should not silently turn a normally local shell into a dependency on a remote network.

Coordinate with systemd instead of racing it

When systemd=true is enabled in the same [boot] section, do not infer ordering details beyond what current WSL documentation guarantees. WSL exposes both settings, but their interaction can depend on the installed runtime and distro setup. Validate the exact workload on the target version. If a task has ordering or readiness dependencies on a systemd service, express those dependencies in a systemd unit rather than hoping the standalone WSL command runs at the right instant.

Use a systemd oneshot unit for work that belongs to a unit dependency graph, needs journal records, or must run after a particular service. Use command for a small distro-start action that genuinely fits the WSL startup hook’s contract. Pick one owner for the operation. Two owners can cause duplicate starts, conflicting cleanup, or confusing status checks.

The hook executes with root privileges. Keep the executable path fixed, ensure ordinary users cannot replace the script, avoid evaluating untrusted environment variables, and never interpolate user-controlled text into a root shell command. Although the goal here is lifecycle reliability rather than a general security review, root execution is a technical fact that should shape how the script is stored and reviewed.

Roll out and roll back safely

For one test distro, preserve the current /etc/wsl.conf, add only the [boot] command line, and verify every existing section remains valid. If a fleet bootstrap mechanism owns the file, update that source of truth rather than editing a generated file on one host. Record the exact WSL package version, Windows build, distro release, script hash, expected result, and rollback condition.

Rollback should remove or comment out the single command key and stop/restart the distro. If the distro still launches but the task is incorrect, inspect the wrapper and its exit status. If normal startup fails, use the supported recovery shell to edit /etc/wsl.conf. Preserve distribution data: wsl --unregister is a destructive removal operation, not a startup-hook repair.

Acceptance criteria

The change is ready when the command runs as root only at the intended distro-start boundary; repeated starts do not duplicate state; normal user shells do not rerun it; expected service or filesystem state is independently verified; errors are observable; startup time remains within an explicit budget; and rollback restores the prior behavior. Keep the action narrow enough that a later maintainer can understand why it exists from the configuration and wrapper name alone.

Related:

Sources:

Comments