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.
| Situation | Best fit | Because |
|---|---|---|
| Node, Python, Go or Rust development targeting Linux servers | WSL2 | Same toolchain as production, near-native speed, no dual boot |
| Docker on a Windows workstation | WSL2 | The WSL2 backend is how containers run on Windows now |
| Windows desktop applications, .NET, native Windows APIs | Native Windows | WSL adds a boundary you would spend the day crossing |
| Kernel work, custom modules, systemd-heavy infrastructure | A full VM | WSL2 constrains what you can change about the kernel |
| GPU compute and machine learning experiments | WSL2 | CUDA and compute pass through, with the caveats in section five |
| Anything requiring strong isolation | A full VM | WSL is integrated with the host by design, which is the opposite of isolation |
02 · INSTALLATION
One command, then confirm you got version 2.
# 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.
# 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.
[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 live | Accessed from | Speed |
|---|---|---|
| Linux filesystem (~/projects) | Linux tools | Native. This is the correct arrangement. |
| Windows filesystem (C:\projects) | Windows tools | Native. Also fine. |
| Windows filesystem (/mnt/c/projects) | Linux tools | Slow. This is the mistake. |
| Linux filesystem (\\wsl$\...) | Windows tools | Usable for editing, slow for bulk operations. |
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 inputin 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
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.
| Symptom | Usual cause | Fix |
|---|---|---|
| Everything is slow | Project files under /mnt/c | Move the repository into the Linux home directory |
| Windows swaps under load | No memory limit configured | Set memory and processors in .wslconfig, then wsl --shutdown |
| Cannot reach a WSL service from Windows | Networking mode | Enable mirrored networking, or bind the service to 0.0.0.0 |
| DNS fails, especially on a VPN | Generated resolv.conf conflicts with the VPN | Enable dnsTunneling, or set generateResolvConf to false and write your own |
| Virtual disk keeps growing | Sparse mode disabled | wsl --manage distro --set-sparse true |
| File watching does not trigger | Cross-filesystem inotify | Same fix as the first row; watchers only work reliably on the native side |
# 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.
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.
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.
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.
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.
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.