Skip to content
WSLDeep Dive Published Updated 8 min readViews unavailable

WSL systemd initTimeout: Diagnose Readiness Before Extending the Startup Window

Use WSL's initTimeout setting carefully: separate systemd initialization latency from failed units, mount delays, and guest startup problems.

When a WSL distribution starts slowly, increasing a timeout can appear to fix the problem while hiding the component that is actually late. WSL’s [boot] initTimeout is specifically documented as the number of milliseconds WSL waits for systemd to initialize. The current Microsoft reference lists a default of 10,000 milliseconds. It is not the same as a systemd service’s own startup timeout, the wait for the Linux kernel to boot, or the timeout for an arbitrary command that a caller launched through wsl.exe.

The right operational question is not “what large number should I set?” It is “which readiness boundary is timing out, and does systemd eventually become usable?” Measure that first. Then adjust the WSL wait only when evidence shows systemd initialization itself needs a longer window on the affected system.

Keep the readiness boundaries separate

WSL startup crosses several layers: the Windows-side WSL runtime starts or reuses its VM, the Linux kernel initializes, the distribution’s init path begins, systemd may become PID 1, and systemd starts units. A command launched afterward may wait on still more work. Microsoft’s WSL configuration reference documents separate global settings for kernelBootTimeout and distributionStartTimeout, as well as the per-distribution initTimeout. Treating all of those as one “boot timeout” leads to ineffective tuning.

Systemd readiness is not synonymous with every service being active. Systemd can finish initialization while a non-critical unit is still starting, has failed, or is waiting on a network mount. Conversely, a caller can reach its own deadline before systemd has completed its initial transaction. The WSL setting does not rewrite a unit’s TimeoutStartSec=, retry policy, or dependency graph.

The setting belongs to /etc/wsl.conf, under [boot], and systemd itself must be enabled for the setting to be meaningful. Microsoft documents systemd support for current WSL versions and says to check wsl --version; WSL 1 does not run the WSL 2 VM and cannot use systemd as the distribution init in this way. Confirm the installed package and Windows build before copying a configuration from a different machine.

Capture a baseline rather than guessing

From Windows, collect the WSL runtime version and distro state. Run commands in PowerShell or Command Prompt, not inside Linux unless using the .exe suffix:

wsl.exe --version
wsl.exe --status
wsl.exe --list --verbose
wsl.exe --distribution Ubuntu --exec sh -lc 'ps -p 1 -o pid,comm,args=; systemctl is-system-running 2>&1 || true'

The PID 1 check tells you which process is acting as init. systemctl is-system-running may report degraded when systemd is up but one or more units failed; that is a different state from systemd not responding. Do not hide that distinction in an acceptance test. If systemctl is unavailable because systemd is not installed or not enabled, first resolve that prerequisite rather than changing a timeout.

For an enabled systemd distribution, inspect the boot analysis after startup:

systemd-analyze time
systemd-analyze blame --no-pager | head -30
systemd-analyze critical-chain --no-pager
systemctl --failed --no-pager
systemctl is-system-running

These are diagnostic views of systemd’s recorded boot and unit state. blame lists unit activation durations but does not prove that a unit was on the critical path; critical-chain helps identify dependency ordering. A slow service may be irrelevant to the point at which systemd itself is considered initialized. Correlate them with the exact symptom, WSL logs, and a measured invocation duration.

To measure from the Windows caller, run the same harmless command several times and record elapsed time. The first call after shutdown may include VM and kernel startup, while later calls may reuse a running instance. Keep cold and warm starts separate. If possible, compare a fresh boot after wsl.exe --terminate Ubuntu with a full VM shutdown using wsl.exe --shutdown; the latter affects every WSL 2 distribution and must be coordinated.

Configure the value without disturbing unrelated settings

Before editing, inspect the existing file:

sudo sed -n '1,200p' /etc/wsl.conf

Preserve its current user, automount, networking, and interop settings. Add or merge the [boot] section, avoiding duplicate section headers:

[boot]
systemd=true
initTimeout=30000

The 30-second value is an example of an explicit test value, not a universal recommendation. The documented default is 10 seconds. Start by testing a modest increase only if logs and repeatable measurements show that systemd becomes ready after the default wait but before a longer threshold. A value that is too high can make genuine boot regressions slower to surface to callers. Do not increase it to compensate for a unit that is blocked forever or repeatedly failing.

After changing /etc/wsl.conf, allow the distribution to stop completely before relaunching it. Microsoft’s guidance explains that WSL may keep the subsystem running after the last visible shell closes. From Windows, wsl.exe --terminate Ubuntu stops one distribution, whereas wsl.exe --shutdown stops all WSL 2 distributions. Choose the narrower action when possible and save work before either operation.

Diagnose common false fixes

If PID 1 is not systemd, verify the correct distribution’s /etc/wsl.conf, spelling of systemd=true, WSL package version, and whether the change was loaded after a full distro stop. A timeout cannot enable systemd by itself. If systemd is PID 1 but systemctl is-system-running reports degraded, inspect failed units and dependencies. Extending initTimeout may merely defer the visible failure.

If the issue occurs during kernel startup before init, investigate the WSL VM’s kernel and global kernelBootTimeout separately. If the distro takes a long time to start after PID 1 is already ready, inspect distribution startup work such as mount configuration and service dependencies; distributionStartTimeout is another global setting and is not interchangeable with the systemd initialization window. Do not tune all three settings at once, because that destroys the ability to attribute an improvement.

A network-dependent unit can wait on VPN connectivity, DNS, or a remote filesystem. That delay is a unit dependency or retry design issue, not evidence that systemd itself initializes slowly. A noninteractive command can also finish before a background unit is ready; the caller should check the service’s actual readiness endpoint instead of assuming a successful wsl.exe process launch proves application availability.

There is also a distinction between systemd’s initial transaction and individual unit timeouts. If a unit has a long TimeoutStartSec=, its own activation may remain in progress after PID 1 is responsive. Conversely, a service manager can report degraded because a failed unit is noncritical to the init process. Read the unit’s journal and dependency chain before changing the WSL wait. systemd-analyze time can summarize manager startup phases, but it is not a portable guarantee that every WSL feature or application has completed initialization.

When a caller repeatedly reports an early timeout, log the command it launched and whether the WSL process itself exits or only the caller abandons its wait. A wrapper may kill wsl.exe at its own deadline, making a later systemd measurement impossible. In a diagnostic harness, keep the caller alive long enough to obtain both the WSL command exit status and the in-guest readiness result. Do not leave a long-running production process without an external deadline merely to collect evidence.

Use a measurable acceptance test

Write down the symptom as a start condition and a readiness condition. For example: “After a cold WSL VM start, the distribution becomes systemd-ready within 25 seconds and the application socket accepts a local health check within 40 seconds.” Measure each boundary independently. Run at least five cold starts under the same Windows power state and record median and worst-case values. Repeat warm starts separately. Include WSL version, Windows build, distro release, configuration, systemd status, failed units, and whether networking or mounts were available.

An acceptable result has stable systemd readiness within the chosen WSL wait and no unexplained increase in service failures. If the longer setting makes the caller stop reporting an early timeout but does not improve readiness or application health, it has not fixed the system. Restore the previous value and repair the underlying unit, mount, or startup dependency.

Change-control guidance

Keep the timeout tied to a reproducible measurement, not a copied forum value. Configuration changes should be tested after WSL updates because the reference describes the supported option but does not promise identical startup duration across Windows builds, kernels, distributions, or service sets. In managed environments, record both the global WSL package and per-distribution /etc/wsl.conf in the runbook. Recheck the PID 1 and unit state after changing either.

initTimeout is useful when the measured systemd initialization phase legitimately exceeds the current wait. It is not a general “make WSL reliable” knob. Diagnose the component that owns the delay, tune only its boundary, and retain a separate health check for the workload that users actually need.

If the distribution runs a large set of services, reduce unnecessary work and remove failed dependencies before extending the wait. A longer initialization window is reasonable only when the observed systemd-ready event consistently lands just beyond the old threshold and the services required by the workload then pass their own health checks. If the duration is highly variable, identify the source of variance first: filesystem checks, first-boot provisioning, CPU contention, or a network dependency can dominate different runs. Keep the baseline and change as separate records so the next WSL update does not silently preserve a timeout that is no longer needed.

Related:

Sources:

Comments