01 · THE DECISION

WSL2 is a real Linux kernel in a lightweight VM.

WSL1 translated Linux system calls into Windows ones. WSL2 runs an actual Linux kernel in a managed virtual machine, which is why compatibility is excellent and why the filesystem boundary matters so much.

SituationBest fitBecause
Node, Python, Go or Rust development targeting Linux serversWSL2Same toolchain as production, near-native speed, no dual boot
Docker on a Windows workstationWSL2The WSL2 backend is how containers run on Windows now
Windows desktop applications, .NET, native Windows APIsNative WindowsWSL adds a boundary you would spend the day crossing
Kernel work, custom modules, systemd-heavy infrastructureA full VMWSL2 constrains what you can change about the kernel
GPU compute and machine learning experimentsWSL2CUDA and compute pass through, with the caveats in section five
Anything requiring strong isolationA full VMWSL is integrated with the host by design, which is the opposite of isolation

02 · INSTALLATION

One command, then confirm you got version 2.

POWERSHELL (ADMIN) · INSTALL
# Enables the features and installs the default distribution
wsl --install

# Or pick one explicitly
wsl --list --online
wsl --install -d Ubuntu-24.04

# After the reboot, confirm the version column says 2
wsl -l -v

# Keep the subsystem itself updated
wsl --update

Choosing a distribution

  • Ubuntu LTS — the default for a reason. The largest share of documentation and CI images assume it, so error messages match search results.
  • Debian — leaner, slower moving. Good when your servers run Debian.
  • Fedora or openSUSE — newer toolchains, more churn. Fine if you already know the ecosystem.
  • Alpine — tempting for size, awkward for development because of the musl C library. Use it in containers, not as your workstation shell.

You can install several side by side and switch with wsl -d name. A per-project distribution is a legitimate way to keep two incompatible toolchains apart, and each one is a file you can export and re-import.

POWERSHELL · SNAPSHOT AND RESTORE A DISTRIBUTION
# Export a distribution to a single archive
wsl --export Ubuntu-24.04 D:\wsl\ubuntu-backup.tar

# Re-import it, under any name, on any machine
wsl --import work-ubuntu D:\wsl\work D:\wsl\ubuntu-backup.tar

03 · THE CONFIG FILE

Create .wslconfig before WSL eats your memory.

By default WSL2 will claim a large share of system RAM and is slow to give it back. On a 16 GB machine, that is the difference between a usable desktop and one that swaps whenever a build starts.

Create .wslconfig in your Windows user profile — C:\Users\yourname\.wslconfig — and restart the subsystem with wsl --shutdown.

C:\USERS\YOURNAME\.WSLCONFIG
[wsl2]
# Roughly half of physical RAM is a sane starting point
memory=8GB
processors=4
swap=4GB

# Reclaim unused memory back to Windows instead of holding it
autoMemoryReclaim=gradual

# Sparse VHD keeps the virtual disk from growing forever
sparseVhd=true

# Mirrored networking makes localhost work in both directions
networkingMode=mirrored
dnsTunneling=true
autoProxy=true

[experimental]
hostAddressLoopback=true

Choosing the numbers

  • Memory — about half of physical RAM. Raise it if builds are being killed, lower it if Windows starts paging.
  • Processors — leave at least two cores for Windows. All of them is not faster once the host starts contending.
  • Swap — worth having. Without it, an out-of-memory situation kills the process instead of slowing down.
  • Networking — mirrored mode makes services reachable on localhost from both sides, which removes the most common WSL networking confusion. If a VPN or corporate network client misbehaves, remove that line first.

The virtual disk grows but does not shrink on its own. With sparseVhd enabled, new distributions release space back after large deletions. For an existing one, wsl --manage <distro> --set-sparse true converts it.

04 · THE ONE BIG MISTAKE

Keep your code on the Linux side. All of it.

This is the single most common WSL2 performance complaint, and it has one cause: working on files that live on the Windows drive, accessed through /mnt/c.

Crossing the filesystem boundary goes through a network protocol. For a compiler or a package manager touching thousands of small files, the overhead is severe — installs and builds that should take seconds take minutes, and file watchers become unreliable.

Where the files liveAccessed fromSpeed
Linux filesystem (~/projects)Linux toolsNative. This is the correct arrangement.
Windows filesystem (C:\projects)Windows toolsNative. Also fine.
Windows filesystem (/mnt/c/projects)Linux toolsSlow. This is the mistake.
Linux filesystem (\\wsl$\...)Windows toolsUsable for editing, slow for bulk operations.
BASH · MOVE A PROJECT ONTO THE LINUX FILESYSTEM
mkdir -p ~/projects
cd ~/projects
git clone git@github.com:you/your-project.git
cd your-project

# Open it in VS Code on Windows, running the server inside WSL
code .

You can still reach these files from Windows through \\wsl$\Ubuntu-24.04\home\you\projects — good for dropping a file into Explorer, wrong for running a Windows build tool against the whole tree.

Never run Windows antivirus real-time scanning across your WSL project directory. Scanning through the filesystem bridge on every file operation is a large, invisible tax on every build. Exclude the WSL virtual disk path, not the individual folders.

05 · WIRING IT UP

Editor, Git, containers, keys and the GPU.

VS Code

Install the WSL extension on Windows and run code . from inside the Linux shell. The editor UI stays on Windows while the language servers, terminal, debugger and extensions run in Linux — which means the extensions see the same toolchain your build does. Trying to open a project through \\wsl$ instead is the setup that produces mysteriously broken IntelliSense.

Git

  • Install and configure Git inside WSL, and use it for anything in the Linux filesystem.
  • Set git config --global core.autocrlf input in Linux so you do not commit Windows line endings.
  • Sharing a credential helper with Windows works, but a plain SSH key inside WSL is simpler and has fewer failure modes.

Docker

Docker Desktop uses WSL2 as its backend and exposes the docker command inside your distributions. If you would rather not run Docker Desktop, you can install the Docker engine directly inside a WSL distribution — the container alternatives guide covers when that is worth the extra setup.

SSH keys

BASH · A KEY THAT LIVES IN WSL
ssh-keygen -t ed25519 -C "you@example.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub   # add this to GitHub

Keep the Linux key separate from your Windows key rather than sharing one across the boundary. Two keys on one account is normal, and it means revoking one does not lock you out of both environments.

GPU compute

CUDA workloads run in WSL2 with the Windows driver providing the GPU — you install the CUDA toolkit inside Linux, but not a Linux display driver. Installing one is the classic mistake and breaks the passthrough. This is what makes WSL2 a reasonable place to run local models; see the local LLM guide for the hardware side.

06 · WHEN IT MISBEHAVES

The six failures you will actually hit.

SymptomUsual causeFix
Everything is slowProject files under /mnt/cMove the repository into the Linux home directory
Windows swaps under loadNo memory limit configuredSet memory and processors in .wslconfig, then wsl --shutdown
Cannot reach a WSL service from WindowsNetworking modeEnable mirrored networking, or bind the service to 0.0.0.0
DNS fails, especially on a VPNGenerated resolv.conf conflicts with the VPNEnable dnsTunneling, or set generateResolvConf to false and write your own
Virtual disk keeps growingSparse mode disabledwsl --manage distro --set-sparse true
File watching does not triggerCross-filesystem inotifySame fix as the first row; watchers only work reliably on the native side
POWERSHELL · THE RESET SEQUENCE
# Stop everything (this is the fix for a surprising number of issues)
wsl --shutdown

# Update the subsystem itself
wsl --update

# Check state and versions
wsl -l -v

# Last resort for one distribution: export, unregister, re-import
wsl --export Ubuntu-24.04 D:\wsl\backup.tar
wsl --unregister Ubuntu-24.04

Export before you unregister. Unregistering deletes the distribution and everything in it, without a confirmation worth the name.

07 · QUICK ANSWERS

WSL2, briefly.

Why is WSL2 so slow for my project?

Almost always because the project files live on the Windows drive and are accessed from Linux through /mnt/c. Crossing that boundary goes through a network protocol, which is punishing for tools that touch thousands of small files. Move the repository into the Linux home directory and the problem disappears.

How much memory should I give WSL2?

Roughly half of physical RAM is a reasonable starting point, set in a .wslconfig file in your Windows user profile. Also set a processor count that leaves at least two cores for Windows, and enable swap so an out-of-memory situation slows down rather than killing the process. Run wsl --shutdown for changes to apply.

Can I run Docker without Docker Desktop on WSL2?

Yes. You can install the Docker engine directly inside a WSL distribution and use it from that shell. Docker Desktop adds convenience such as the GUI, Kubernetes and easier cross-distribution sharing, so the plain engine is best when you want a lighter setup or need to avoid the Desktop licence terms.

Does WSL2 support GPU acceleration?

Yes, for compute. The Windows GPU driver provides passthrough, and you install the CUDA toolkit inside Linux without a Linux display driver. Installing a Linux graphics driver inside WSL breaks the passthrough, which is the most common mistake in this setup.

Is WSL2 a replacement for a virtual machine?

For development work targeting Linux, usually yes, and it is faster to start and lighter on resources. For kernel development, custom modules, systemd-heavy infrastructure or anything requiring real isolation from the host, use a full virtual machine — WSL is deliberately integrated with Windows rather than separated from it.