WSL2 ARCHITECTURE Windows 10/11 Host (NT Kernel + Hyper-V) Lightweight Utility VM (Real Linux Kernel 5.15+) Ubuntu 24.04 apt, bash, git Debian 12 Node.js, Python Docker Engine Containers VS Code Remote-WSL Multiple Linux distributions share a single lightweight VM with full kernel support

Windows Subsystem for Linux 2 (WSL2) has fundamentally changed how developers work on Windows. Instead of dual-booting, running heavy virtual machines, or struggling with compatibility layers, you can now run a full Linux environment natively alongside Windows with near-bare-metal performance. Whether you write Node.js, Python, Go, Rust, or any other language, WSL2 gives you genuine Linux tooling without leaving your Windows desktop.

This guide walks you through everything you need to set up a professional-grade Linux development environment on Windows using WSL2. We will cover installation, Ubuntu configuration, Windows Terminal setup, Docker integration, VS Code Remote development, file system best practices, networking, GPU support, and managing multiple distributions.

Prerequisites

Before you begin, make sure you have:

  • Windows 10 version 2004 (build 19041) or later, or Windows 11
  • At least 8 GB of RAM (16 GB recommended for Docker workloads)
  • Virtualization enabled in your BIOS/UEFI (Intel VT-x or AMD-V)
  • An internet connection to download distributions
  • PowerShell or Windows Terminal with Administrator privileges

Note: If you are running Windows 10, make sure all Windows Updates are installed. Older builds may have partial WSL2 support with known bugs. Windows 11 provides the best WSL2 experience, including systemd support and native GUI application rendering.

What Is WSL2?

WSL2 (Windows Subsystem for Linux version 2) is a compatibility layer built into Windows that allows you to run Linux binary executables natively. Unlike WSL1, which translated Linux system calls into Windows NT kernel calls, WSL2 runs a real Linux kernel inside a lightweight Hyper-V virtual machine.

Key characteristics of WSL2:

  • Real Linux kernel: WSL2 ships with a Microsoft-maintained Linux kernel (based on kernel 5.15+ as of 2025) that receives regular updates through Windows Update.
  • Full system call compatibility: Because it runs a genuine kernel, WSL2 supports tools like Docker, systemd, FUSE file systems, and eBPF that WSL1 could not handle.
  • Lightweight: The virtual machine starts in about one second and consumes minimal resources when idle.
  • Tight Windows integration: You can call Windows executables from Linux, access Windows files from Linux (and vice versa), and use localhost networking between the two systems.
# Check your current WSL version
wsl --version

WSL1 vs WSL2

Understanding the differences helps you choose the right version for your workflow:

FeatureWSL1WSL2
ArchitectureTranslation layerLightweight VM with real kernel
Linux kernelNone (syscall translation)Full Linux kernel
File system performance (Linux files)ModerateNative ext4 speed
File system performance (Windows files)Fast (direct NTFS access)Slower (9P protocol)
System call compatibilityPartial (~70%)Full (100%)
Docker supportNoYes
systemd supportNoYes (Windows 11)
Memory usageLowerDynamic (grows/shrinks)
Boot timeInstant~1 second
NetworkingShares Windows network stackVirtual ethernet adapter

For most developers, WSL2 is the correct choice. The only scenario where WSL1 might be preferable is when you must heavily access files stored on the Windows NTFS partition, since WSL1 has faster cross-OS file access.

Installing WSL2 and Ubuntu

Microsoft has simplified the installation process significantly. On modern Windows builds, a single command handles everything:

Open PowerShell as Administrator and run:

wsl --install

This command enables the required Windows features (Virtual Machine Platform and Windows Subsystem for Linux), downloads the latest WSL2 Linux kernel, sets WSL2 as the default, and installs Ubuntu.

Restart your computer when prompted:

# After restart, Ubuntu will launch automatically for first-time setup
# You will be prompted to create a UNIX username and password

Manual installation (older Windows builds)

If wsl --install is not available, enable the features manually:

# Enable WSL feature
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

# Enable Virtual Machine Platform
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# Restart your computer, then set WSL2 as default
wsl --set-default-version 2

Install a specific distribution

You can choose from several distributions:

# List all available distributions
wsl --list --online

# Install a specific distribution
wsl --install -d Ubuntu-24.04

# Other popular options:
# wsl --install -d Debian
# wsl --install -d openSUSE-Tumbleweed
# wsl --install -d kali-linux

Initial Ubuntu Configuration

After your Ubuntu distribution launches for the first time and you create your user account, run these essential configuration steps:

Update the system

sudo apt update && sudo apt upgrade -y

Install essential development tools

sudo apt install -y build-essential git curl wget unzip zip \
  software-properties-common apt-transport-https \
  ca-certificates gnupg lsb-release

Configure Git

git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
git config --global init.defaultBranch main
git config --global core.autocrlf input

Important: Setting core.autocrlf to input ensures that Git converts Windows-style line endings (CRLF) to Unix-style (LF) on commit but leaves LF endings untouched on checkout. This prevents line-ending issues when sharing code between Windows and Linux tools.

Generate SSH keys

ssh-keygen -t ed25519 -C "your.email@example.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Display the public key to add to GitHub/GitLab
cat ~/.ssh/id_ed25519.pub

Set up a better shell prompt (optional)

Many developers prefer Zsh with Oh My Zsh for a more productive terminal experience:

sudo apt install -y zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Windows Terminal Setup

Windows Terminal is the recommended terminal application for WSL2. It supports multiple tabs, split panes, GPU-accelerated text rendering, and deep customization.

Installation

Install Windows Terminal from the Microsoft Store or via winget:

winget install --id Microsoft.WindowsTerminal -e

Configure Ubuntu as the default profile

Open Windows Terminal Settings (Ctrl+,) and set your Ubuntu profile as the default. In the settings.json file, you can also customize the appearance:

{
  "defaultProfile": "{YOUR-UBUNTU-GUID}",
  "profiles": {
    "list": [
      {
        "name": "Ubuntu",
        "source": "Windows.Terminal.Wsl",
        "startingDirectory": "//wsl$/Ubuntu/home/yourusername",
        "fontFace": "CascadiaCode NF",
        "fontSize": 11,
        "colorScheme": "One Half Dark",
        "cursorShape": "filledBox"
      }
    ]
  }
}

Useful keyboard shortcuts

ShortcutAction
Ctrl+Shift+TNew tab
Ctrl+Shift+DDuplicate pane
Alt+Shift+DSplit pane
Ctrl+TabSwitch tabs
Ctrl+Shift+WClose pane

File System Best Practices

Understanding file system performance in WSL2 is critical for a productive workflow. This is one of the most common sources of confusion and frustration for new WSL2 users.

The golden rule

Store your project files inside the Linux file system, not on the Windows drive.

# FAST: Files in your Linux home directory
# Path: ~/projects/my-app
# Actual location: ext4 file system inside WSL2 VM
cd ~/projects/my-app
time git status  # ~0.1 seconds

# SLOW: Files on the Windows drive accessed from WSL2
# Path: /mnt/c/Users/yourname/projects/my-app
# Crosses the 9P protocol bridge on every file operation
cd /mnt/c/Users/yourname/projects/my-app
time git status  # ~2-5 seconds (10-50x slower)

Why the performance difference exists

WSL2 runs inside a lightweight VM with its own ext4 file system. Accessing files on the Windows NTFS partition requires crossing the VM boundary using the 9P protocol, which adds latency to every file operation. For a node_modules folder with thousands of small files, this overhead becomes dramatic.

Accessing files across boundaries

Even though you should store projects on the Linux side, you can still access files from both systems:

# From WSL2, access Windows files
ls /mnt/c/Users/yourname/Documents

# From Windows Explorer, access Linux files
# Type this in the Explorer address bar:
# \\wsl$\Ubuntu\home\yourusername\projects
# From PowerShell, access Linux files
explorer.exe \\wsl$\Ubuntu\home\yourusername
mkdir -p ~/projects ~/tools ~/scripts
# Keep all development work under ~/projects
# Keep downloaded tools under ~/tools
# Keep automation scripts under ~/scripts

Docker Desktop Integration with WSL2

Docker Desktop for Windows uses WSL2 as its backend, providing native Linux container performance without the overhead of a traditional Hyper-V VM.

Installation

  1. Download and install Docker Desktop for Windows.
  2. During installation, ensure “Use WSL 2 instead of Hyper-V” is selected.
  3. After installation, open Docker Desktop Settings and navigate to Resources > WSL Integration.
  4. Enable integration with your Ubuntu distribution.

Verify the installation

From your WSL2 Ubuntu terminal:

docker --version
docker compose version
docker run hello-world

Resource management

Docker Desktop with WSL2 can consume significant memory. Configure limits in ~/.wslconfig on the Windows side:

# Create/edit C:\Users\yourname\.wslconfig
[wsl2]
memory=8GB
processors=4
swap=2GB

After modifying .wslconfig, restart WSL2:

wsl --shutdown

Running containers

Since Docker runs inside the WSL2 VM, you get full Linux container performance:

# Run an Nginx container
docker run -d -p 8080:80 --name webserver nginx

# Access it from both WSL2 and Windows browser at http://localhost:8080

# Run a development database
docker run -d -p 5432:5432 \
  -e POSTGRES_PASSWORD=devpassword \
  --name devdb postgres:16

# Use Docker Compose for multi-container setups
docker compose up -d

For a complete Docker installation guide on Ubuntu, see our article on How to Install Docker on Ubuntu.

VS Code Remote - WSL Extension

Visual Studio Code’s Remote - WSL extension lets you use VS Code on Windows while running all tools, terminals, and extensions inside WSL2. This is the recommended way to edit code stored on the Linux file system.

Setup

  1. Install Visual Studio Code on Windows (not inside WSL2).
  2. Install the WSL extension (identifier: ms-vscode-remote.remote-wsl).
  3. Open a WSL2 terminal and navigate to your project directory.
  4. Launch VS Code from the terminal:
cd ~/projects/my-app
code .

VS Code will install its server component inside WSL2 automatically and connect to it. You will see “WSL: Ubuntu” in the bottom-left corner of VS Code, confirming you are running in remote mode.

Key benefits

  • Extensions run inside WSL2: Language servers, linters, debuggers, and formatters execute in the Linux environment, eliminating cross-OS compatibility issues.
  • Terminal is a real Linux shell: The integrated terminal is your WSL2 bash/zsh, not PowerShell.
  • File watching works natively: Hot-reload for frameworks like React, Vue, and Next.js works without additional configuration because the file watcher operates on the Linux file system.
  • Git integration uses Linux Git: VS Code uses the Git binary inside WSL2, avoiding line-ending and path issues.

Install these extensions inside the WSL2 environment (they will appear under “WSL: Ubuntu - Installed”):

# From inside WSL2 terminal
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension ms-python.python
code --install-extension golang.go
code --install-extension bradlc.vscode-tailwindcss

Networking Between Windows and WSL2

WSL2 networking has evolved significantly. On modern Windows 11 builds with WSL2 2.0+, networking uses mirrored mode by default, which simplifies most connectivity scenarios.

Accessing WSL2 services from Windows

By default, services running inside WSL2 are accessible from Windows via localhost:

# Start a development server in WSL2
python3 -m http.server 3000

# Access it from Windows browser: http://localhost:3000

Accessing Windows services from WSL2

You can reach Windows services from WSL2 using localhost as well (mirrored mode on Windows 11), or use the Windows host IP:

# Find the Windows host IP (useful for older builds)
cat /etc/resolv.conf | grep nameserver
# Output example: nameserver 172.28.80.1

# Or use the hostname
ping "$(hostname).local"

Configure mirrored networking (Windows 11)

Add to your .wslconfig file on Windows:

# C:\Users\yourname\.wslconfig
[wsl2]
networkingMode=mirrored
dnsTunneling=true
autoProxy=true

Port forwarding for external access

If you need external devices to reach services running in WSL2:

# Forward port 3000 from Windows to WSL2 (run as Administrator)
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=localhost

# Remove the forwarding rule when no longer needed
netsh interface portproxy delete v4tov4 listenport=3000 listenaddress=0.0.0.0

# List all forwarding rules
netsh interface portproxy show v4tov4

GPU and CUDA Support

WSL2 supports GPU passthrough, allowing you to run CUDA workloads, machine learning frameworks, and even graphical Linux applications directly.

Prerequisites

  • An NVIDIA GPU with a recent Windows driver (Game Ready or Studio driver 470.76+)
  • Windows 11 or Windows 10 build 21H2+

Verify GPU access

# Check if the GPU is visible
nvidia-smi

# You should see your GPU model, driver version, and CUDA version

Install CUDA Toolkit inside WSL2

# Do NOT install a Linux NVIDIA driver inside WSL2 -- use the Windows driver
# Only install the CUDA toolkit

wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt update
sudo apt install -y cuda-toolkit

Test with PyTorch

pip install torch torchvision
python3 -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}'); print(f'Device: {torch.cuda.get_device_name(0)}')"

Important: Never install a Linux NVIDIA display driver inside WSL2. The Windows GPU driver handles the GPU passthrough. Installing a Linux driver will cause conflicts.

Managing Multiple Distributions

WSL2 allows you to run multiple Linux distributions simultaneously, which is useful for testing across different environments or isolating workloads.

Install additional distributions

# List available distributions
wsl --list --online

# Install additional distributions
wsl --install -d Debian
wsl --install -d Ubuntu-22.04

Switch between distributions

# List installed distributions and their status
wsl --list --verbose

# Launch a specific distribution
wsl -d Debian

# Set a default distribution
wsl --set-default Ubuntu-24.04

Export and import distributions

This is useful for creating backups or sharing pre-configured environments with your team:

# Export a distribution to a tar file
wsl --export Ubuntu-24.04 D:\backups\ubuntu-24.04-backup.tar

# Import a distribution from a tar file
wsl --import MyCustomUbuntu D:\wsl\MyCustomUbuntu D:\backups\ubuntu-24.04-backup.tar

# Launch the imported distribution
wsl -d MyCustomUbuntu

Remove a distribution

# Unregister and delete a distribution (WARNING: destroys all data)
wsl --unregister Debian

WSL Commands Reference

Here is a comprehensive reference table of the most important WSL commands:

CommandDescription
wsl --installInstall WSL with default Ubuntu distribution
wsl --install -d <distro>Install a specific distribution
wsl --list --onlineList all available distributions
wsl --list --verboseList installed distributions with version and state
wsl --set-default-version 2Set WSL2 as default for new installations
wsl --set-default <distro>Set the default distribution
wsl --set-version <distro> 2Convert a WSL1 distribution to WSL2
wsl --shutdownShut down all running distributions and the VM
wsl --terminate <distro>Terminate a specific distribution
wsl --export <distro> <file>Export a distribution to a tar file
wsl --import <name> <path> <file>Import a distribution from a tar file
wsl --unregister <distro>Remove a distribution and delete all its data
wsl --updateUpdate the WSL2 Linux kernel
wsl --versionDisplay WSL version, kernel version, and WSLg version
wsl --statusShow WSL configuration and default distribution
wsl -d <distro> -u rootLaunch a distribution as root user
wsl hostname -IDisplay the IP address of the WSL2 VM

Troubleshooting

WSL2 fails to start with a virtualization error

If you see an error like “Please enable the Virtual Machine Platform Windows feature”, verify that virtualization is enabled in your BIOS/UEFI:

# Check if virtualization is enabled
systeminfo | findstr /i "Hyper-V"

# Re-enable the required features
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all

WSL2 uses too much memory

By default, WSL2 can consume up to 50% of your total system memory. Create or edit C:\Users\yourname\.wslconfig:

[wsl2]
memory=4GB
swap=2GB

Then restart WSL2:

wsl --shutdown

DNS resolution fails inside WSL2

If ping google.com fails but ping 8.8.8.8 works, DNS is the issue:

# Temporary fix: manually set DNS
sudo rm /etc/resolv.conf
sudo bash -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
sudo bash -c 'echo "nameserver 8.8.4.4" >> /etc/resolv.conf'

# Prevent WSL from overwriting resolv.conf
sudo bash -c 'echo "[network]" > /etc/wsl.conf'
sudo bash -c 'echo "generateResolvConf = false" >> /etc/wsl.conf'

Then restart WSL2 with wsl --shutdown from PowerShell.

Clock drift between Windows and WSL2

After a Windows sleep/hibernate cycle, the WSL2 clock can drift:

# Check the clock
date

# Sync the clock manually
sudo hwclock -s

# Or on newer builds
sudo ntpdate time.windows.com

File permissions are wrong on Windows-mounted drives

# Add to /etc/wsl.conf inside your distribution
[automount]
enabled = true
options = "metadata,umask=22,fmask=11"
mountFsTab = false

”Cannot connect to Docker daemon” error

# Verify Docker Desktop is running on Windows
# Then check the WSL2 integration setting in Docker Desktop:
# Settings > Resources > WSL Integration > Enable for your distro

# Restart WSL2
wsl --shutdown

# Verify Docker works
docker ps

Summary

WSL2 transforms Windows into a first-class development platform for Linux-based workflows. With a real Linux kernel, native file system performance, Docker integration, and seamless VS Code connectivity, you can enjoy the best of both operating systems without compromise.

To get the most out of your WSL2 environment:

  1. Always store project files on the Linux file system for optimal performance.
  2. Use Windows Terminal with customized profiles for each distribution.
  3. Leverage VS Code Remote - WSL to keep your editing experience on Windows while executing everything in Linux.
  4. Configure .wslconfig to manage memory and processor allocation for your workloads.
  5. Use Docker Desktop with the WSL2 backend for container workloads — see our complete Docker installation guide for more details.
  6. Automate your workflows with CI/CD pipelines once your development environment is ready. Check our guide on Getting Started with GitHub Actions for CI/CD to take your projects to the next level.

With WSL2 properly configured, you have a powerful, flexible, and performant Linux development environment running right on your Windows machine.