0 / 25 done
0 XP
AY
Atharv Yadav github.com/atharvbyadav
🐧

Master WSL
The Fun Way

Windows Subsystem for Linux lets you run a full Linux environment right inside Windows — no dual boot, no VM headaches. This guide turns complex concepts into bite-sized, interactive lessons.

⬇️
Install WSL

Get WSL 2 running on your machine in under 5 minutes.

4 lessons • ~10 min
🐋
Dev Environment

Set up VS Code, Docker, Git and SSH for serious development.

4 lessons • ~20 min
🎮
Advanced WSL

GPU passthrough, mirrored networking, custom distros and more.

6 lessons • ~30 min
🔧
Fix Problems

Diagnose and fix the most common WSL issues quickly.

3 lessons • ~15 min
📖
Lesson 1

What is WSL?

Understand what Windows Subsystem for Linux actually is, why it exists and how it changed the Windows developer experience forever.

+20XP
Complete to earn

🤔 The Problem WSL Solves

Before WSL, Windows developers who needed Linux tools had a rough time. You either dual-booted (restart every time you need Linux), ran a heavy VM (slow, resource-hungry) or used Cygwin/MSYS (incomplete compatibility). None of these were great.

WSL changes everything by letting you run real Linux binaries directly on Windows — no full VM overhead, no rebooting, no compromises.

🐧
Real Linux Kernel

WSL 2 runs a real, Microsoft-maintained Linux kernel inside a lightweight VM. It's not emulation — it's the actual thing.

Near-Native Performance

File I/O on the Linux filesystem (ext4 VHD) is blazing fast. No more waiting around for npm install.

🔗
Deep Windows Integration

Call Windows executables from Linux and vice versa. Share files, environment variables and network ports.

🖥️
GUI App Support

WSLg lets you run Linux GUI apps (Firefox, GIMP, VS Code) with no extra setup. They just... appear.

🏗️ How WSL 2 Works

WSL 2 is architecturally very different from WSL 1. Instead of translating Linux system calls to Windows (like WSL 1 did), WSL 2 runs a full Linux kernel inside a lightweight Hyper-V VM. The VM is so tightly integrated that it feels like a local process, not a virtual machine.

💡
WSL 2 Architecture
Hyper-V VM → Real Linux Kernel → Your distro (Ubuntu/Debian/etc) → Your shell. The VM starts in under 2 seconds and uses only what memory it needs.
🧠 Quick Check
How does WSL 2 run Linux differently from WSL 1?
🔍
Lesson 2

Requirements

Make sure your system can run WSL 2. This is quick — most modern Windows machines are already good to go.

+10XP
Complete to earn

✅ Minimum Requirements

Feature Requirement Your Build Needs
WSL 2 (basic)Windows 10 or 11Build 19041+ (May 2020)
WSLg (GUI apps)Windows 11Build 22000+ or Windows 10 Insider
GPU / CUDAWindows 11 or Win 10 21H2+Build 19044+
Mirrored NetworkingWindows 11WSL 0.67.6+
Sparse VHDWindows 11WSL 2.0.0+

🖥️ Check Your Windows Build

Run this in PowerShell to see your Windows version and build number:

PowerShell
Get-ComputerInfo | Select-Object WindowsVersion, OsBuildNumber

🔲 Enable Required Features

WSL 2 needs two Windows features enabled. Run these in PowerShell as Administrator:

PowerShell (Admin)
# 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
⚠️
Virtualization Must Be Enabled in BIOS
If WSL 2 won't start, check that Intel VT-x or AMD-V is enabled in your BIOS/UEFI firmware settings. This is usually under "CPU Configuration" or "Advanced".
⬇️
Lesson 3

Installation

Install WSL 2 with a single command. Seriously, it's that easy now.

+25XP
Complete to earn

🚀 One-Command Install

Open PowerShell as Administrator and run:

PowerShell (Admin)
wsl --install

This installs WSL 2 with Ubuntu as the default distro. Restart your PC when prompted, then Ubuntu will finish setup.

1
Run the install command

Open PowerShell as Admin. Run wsl --install. Wait for it to finish.

2
Restart your computer

WSL needs a reboot to finish setting up the kernel. Don't skip this.

3
Ubuntu finishes setup

After reboot, Ubuntu opens automatically. Set your Linux username and password.

4
Verify it worked

Run wsl --version and wsl -l -v to confirm everything is running.

PowerShell
wsl --version
wsl -l -v

🐧 Install a Different Distro

PowerShell
# See available distros
wsl --list --online

# Install a specific one
wsl --install -d Debian
wsl --install -d kali-linux
wsl --install -d Ubuntu-24.04
🎉
Lesson 4

First Run Setup

WSL is installed. Now let's get your Linux environment production-ready.

+20XP
Complete to earn
1
Create your Linux user

On first launch, Ubuntu asks for a username and password. This is your Linux user — separate from your Windows account. Pick anything you like (lowercase recommended).

2
Update your packages

Always do this first. Keeps your system secure and current.

bash
sudo apt update && sudo apt upgrade -y
3
Install essential tools
bash
sudo apt install -y curl wget git build-essential unzip
4
Verify your environment
bash
uname -r    # Should show Linux kernel version
whoami      # Your Linux username
pwd         # /home/yourusername
5
Optional: Switch to Zsh

Many devs prefer Zsh with Oh My Zsh for a better shell experience.

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

WSL 1 vs WSL 2

Understanding the difference helps you make the right choice for your workflow.

+15XP
Complete to earn

📊 Feature Comparison

FeatureWSL 1WSL 2
ArchitectureSyscall translationReal Linux kernel (Hyper-V)
Linux filesystem performanceSlower⚡ Much faster
Windows filesystem speedFastSlower (cross-OS)
Docker support❌ No✅ Yes
GPU / CUDA❌ No✅ Yes
systemd❌ No✅ Yes (opt-in)
Full kernel compatibilityPartial✅ Yes
WSLg (GUI apps)❌ No✅ Yes
Boot timeInstant~1-2 seconds
💚
When WSL 1 Still Makes Sense
If you primarily work with files on the Windows filesystem (C:\Users\...) and don't need Docker or GPU support, WSL 1 avoids the cross-OS filesystem performance penalty. For everyone else: WSL 2 is the clear choice.

🔄 Switch Between Versions

PowerShell
# Set default WSL version for new installs
wsl --set-default-version 2

# Switch a specific distro to WSL 2
wsl --set-version Ubuntu 2

# Check current versions
wsl -l -v
🐳
Lesson 6

Distro Management

Install multiple distros, switch between them, back them up and move them around.

+20XP
Complete to earn

🗂️ Lifecycle Commands

PowerShell
# List all installed distros with version and status
wsl -l -v

# Launch a specific distro
wsl -d Debian

# Set the default distro
wsl --set-default Ubuntu

# Stop a specific distro
wsl -t Ubuntu

# Stop ALL distros (full shutdown)
wsl --shutdown

# Remove a distro (DELETES ALL DATA)
wsl --unregister OldDistro

💾 Backup & Restore

PowerShell
# Export distro to a .tar.gz file
wsl --export Ubuntu C:\Backups\ubuntu-backup.tar.gz

# Import it back (or to a new machine)
wsl --import Ubuntu C:\WSL\Ubuntu C:\Backups\ubuntu-backup.tar.gz --version 2
⚠️
Default User After Import
After importing, the distro defaults to root. Fix it: add [user] + default=yourusername to /etc/wsl.conf inside the distro, then run wsl --shutdown.
💾
Lesson 7

Filesystem

The #1 performance gotcha in WSL — and how to avoid it.

+25XP
Complete to earn
🚨
The Golden Rule of WSL Performance
Always store your project files on the Linux filesystem (~/projects/, /home/yourname/) — NOT on the Windows drive (/mnt/c/). Cross-OS filesystem access is 5–10x slower. This single rule makes the biggest difference.

🗺️ Path Mapping

FromYou SeeWindows Equivalent
Linux home~/ or /home/user/\\wsl$\Ubuntu\home\user\
Windows C drive/mnt/c/C:\
Windows desktop/mnt/c/Users/Name/Desktop/C:\Users\Name\Desktop\
WSL from ExplorerOpen Explorer → type \\wsl$Directly browse Linux files

🔄 Path Conversion

bash
# Convert Linux path to Windows path
wslpath -w ~/myproject
# → \\wsl.localhost\Ubuntu\home\user\myproject

# Convert Windows path to Linux path
wslpath -u 'C:\Users\Name\Downloads'
# → /mnt/c/Users/Name/Downloads

# Open current Linux folder in Windows Explorer
explorer.exe .
🔗
Lesson 8

Interoperability

Call Linux commands from PowerShell. Call Windows executables from bash. Share environment variables across worlds.

+20XP
Complete to earn

🪟 → 🐧 Call Linux from Windows

PowerShell
# Run any Linux command from PowerShell
wsl ls -la
wsl grep -r "TODO" ./src

# Pipe between PowerShell and Linux
Get-Content file.txt | wsl grep "pattern"
wsl cat /etc/hosts | Select-String "localhost"

🐧 → 🪟 Call Windows from Linux

bash
# Open Windows Explorer in current dir
explorer.exe .

# Open a file in Windows Notepad
notepad.exe myfile.txt

# Copy text to Windows clipboard
echo "hello!" | clip.exe

# Run PowerShell from bash
powershell.exe -Command "Get-Date"
🌐
Lesson 9

.wslconfig

Global VM settings that apply to all your WSL distros — tune memory, CPU, networking and more.

+20XP
Complete to earn

📁 Location

Create this file at: C:\Users\YourName\.wslconfig

This file configures the WSL 2 virtual machine globally. Changes take effect after running wsl --shutdown.

⚙️ Full Reference Config

.wslconfig
[wsl2]
# Max memory for the WSL VM (default: 50% of host RAM)
memory=8GB

# Swap space
swap=4GB

# Number of virtual processors (default: same as host)
processors=4

# Max VHD disk size
diskSizeGB=256

# Networking mode: 'nat' (default) or 'mirrored' (Win11 only)
networkingMode=nat

# DNS tunneling (useful with VPNs)
dnsTunneling=true

# Allow Windows Firewall rules to apply in WSL
firewall=true

# Return unused memory pages to Windows (helps with RAM usage)
pageReporting=true

# Enable GUI apps (WSLg)
guiApplications=true

# Enable nested virtualization (for running Docker-in-Docker)
nestedVirtualization=false
🐧
Lesson 10

/etc/wsl.conf

Per-distro configuration. Each distro can have its own settings.

+15XP
Complete to earn

📁 Location

Create/edit inside your distro at: /etc/wsl.conf

Run wsl --shutdown then relaunch your distro to apply changes.

⚙️ Full Reference Config

/etc/wsl.conf
[boot]
# Enable systemd (recommended!)
systemd=true
# Run a command on WSL start
command=""

[automount]
# Auto-mount Windows drives (/mnt/c etc)
enabled=true
# Mount options
options="metadata,uid=1000,gid=1000,umask=022,fmask=11"

[network]
# Auto-generate /etc/hosts from Windows hosts file
generateHosts=true
# Auto-generate /etc/resolv.conf for DNS
generateResolvConf=true

[interop]
# Allow calling Windows executables from Linux
enabled=true
# Append Windows PATH to Linux PATH
appendWindowsPath=true

[user]
# Default user (important after wsl --import)
default=yourusername
🌍
Lesson 11

Networking

How WSL connects to the network and how to fix common issues.

+15XP
Complete to earn

🔌 NAT Mode (Default)

In NAT mode, WSL gets its own private IP address and shares Windows' internet connection. Ports you open in WSL are accessible from Windows via localhost.

bash
# Find WSL's IP address
ip addr show eth0 | grep "inet "

# Find Windows host IP from inside WSL
ip route show default | awk '{print $3}'

🔧 Fix DNS Issues

bash
# Manual DNS fix
sudo tee /etc/resolv.conf <<'EOF'
nameserver 1.1.1.1
nameserver 8.8.8.8
EOF

# Prevent WSL from overwriting it
sudo chattr +i /etc/resolv.conf
⚙️
Lesson 12

systemd

Enable systemd to use service management, timers and native Linux init.

+15XP
Complete to earn

🔧 Enable systemd

bash
# Edit /etc/wsl.conf
sudo tee /etc/wsl.conf <<'EOF'
[boot]
systemd=true
EOF

# Then in PowerShell:
# wsl --shutdown
# Then relaunch your distro

✅ Verify & Use

bash
# Verify systemd is PID 1
ps -p 1 -o comm=

# Common systemctl commands
sudo systemctl start nginx
sudo systemctl enable nginx   # Auto-start on WSL launch
sudo systemctl status nginx
journalctl -u nginx -f        # Follow logs
🎨
Lesson 13

VS Code + WSL

The best IDE experience for WSL development. Open WSL projects directly in VS Code from Windows.

+20XP
Complete to earn
1
Install VS Code on Windows

Download from code.visualstudio.com. Install normally on Windows, not inside WSL.

2
Install the WSL Extension

In VS Code, press Ctrl+Shift+X, search for "WSL" and install the official Microsoft extension.

3
Open WSL projects in VS Code
bash
# From inside WSL, open current folder in VS Code
code .

# Or open a specific project
code ~/myproject
🐋
Lesson 14

Docker in WSL 2

Run Docker natively inside WSL 2 without Docker Desktop — lighter, faster, free.

+25XP
Complete to earn

🐋 Install Docker Engine (No Desktop Required)

bash
# Install dependencies
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# Add Docker's GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list

# Install Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Run Docker without sudo
sudo usermod -aG docker $USER
newgrp docker

# Start on boot (requires systemd)
sudo systemctl enable --now docker
🚀
Performance Tip
Store Docker volumes in the Linux filesystem (~/volumes/ or /var/lib/docker) not in /mnt/c/. This avoids cross-OS I/O overhead and makes containers much faster.
🔑
Lesson 15

SSH Keys

Generate and manage SSH keys in WSL for GitHub, remote servers and more.

+15XP
Complete to earn

🗝️ Generate a Key

bash
# Generate ed25519 key (recommended)
ssh-keygen -t ed25519 -C "[email protected]"

# Or RSA (for older systems)
ssh-keygen -t rsa -b 4096 -C "[email protected]"

# Start ssh-agent and add your key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Copy public key for GitHub
cat ~/.ssh/id_ed25519.pub

🔄 Persistent ssh-agent (auto-start)

bash
# Install keychain, then add to ~/.bashrc or ~/.zshrc
sudo apt install -y keychain
echo 'eval $(keychain --eval --quiet ~/.ssh/id_ed25519)' >> ~/.bashrc
🌿
Lesson 16

Git Setup

Configure Git properly in WSL — the right user, editor, line endings and Windows Credential Manager.

+20XP
Complete to earn

⚙️ Essential Config

bash
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
git config --global init.defaultBranch main
git config --global core.autocrlf input    # Critical for cross-platform
git config --global core.editor "code --wait"
git config --global pull.rebase false

🪟 Use Windows Credential Manager

bash
# Use Windows Credential Manager for HTTPS auth
git config --global credential.helper "/mnt/c/Program\\ Files/Git/mingw64/bin/git-credential-manager.exe"
🎮
Lesson 17

GPU & CUDA

Run machine learning workloads inside WSL with full GPU acceleration.

+30XP
Complete to earn
ℹ️
GPU Support in WSL 2
NVIDIA GPUs: driver 470.76+. AMD GPUs: experimental support. Intel oneAPI: check intel.com/wsl. The GPU driver is installed on Windows only — do NOT install GPU drivers inside WSL.
1
Install NVIDIA driver on Windows

Download and install the latest Game Ready or Studio driver from nvidia.com. Do this on Windows, not inside WSL.

2
Install CUDA Toolkit inside WSL
bash
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/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
3
Verify GPU access
bash
nvidia-smi     # Should show your GPU
nvcc --version  # CUDA compiler version

# Test with PyTorch
python3 -c "import torch; print(torch.cuda.is_available())"
Lesson 18

Performance Tuning

Squeeze every bit of speed out of your WSL setup.

+20XP
Complete to earn

🏎️ Key Tuning Areas

📁
File Location (Most Important)

Work in ~/projects, not /mnt/c/. This alone can give 5–10x faster I/O.

👁️
inotify Watchers

Node.js and Vite need lots of file watchers. Increase the kernel limit.

💾
Memory Limits

Set memory= in .wslconfig to prevent WSL from using too much RAM.

📊
Kernel Params

Tune vm.swappiness and net buffers for server workloads.

🔧 Quick Wins

bash
# Increase inotify watchers (for Vite, Webpack, etc.)
echo fs.inotify.max_user_watches=524288 | sudo tee /etc/sysctl.d/99-wsl.conf
sudo sysctl --system

# Reduce swap pressure
echo vm.swappiness=10 | sudo tee -a /etc/sysctl.d/99-wsl.conf

# Release cached memory
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'

# Benchmark disk speed
dd if=/dev/zero of=/tmp/test bs=1M count=1024 oflag=direct 2>&1 | tail -1
🛠️
Lesson 19

Custom Distros

Import any Linux distro into WSL — Alpine, Arch or your own custom Docker image.

+25XP
Complete to earn

🏔️ Import Alpine Linux

bash
# Download Alpine minirootfs
wget https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.21.0-x86_64.tar.gz

# In PowerShell: import it
# wsl --import Alpine C:\WSL\Alpine .\alpine-minirootfs-3.21.0-x86_64.tar.gz --version 2
# wsl -d Alpine

🐳 Build from Docker Image

bash
# Build and export a Docker image as a WSL distro
docker build -t my-distro .
docker run --name tmp-distro my-distro true
docker export tmp-distro | gzip > my-distro.tar.gz
docker rm tmp-distro

# In PowerShell
# wsl --import MyDistro C:\WSL\MyDistro .\my-distro.tar.gz --version 2
🖥️
Lesson 20

GUI Apps with WSLg

Run Linux graphical apps seamlessly on Windows. No X server needed.

+20XP
Complete to earn

🎨 Enable & Install GUI Apps

First enable in .wslconfig: guiApplications=true (enabled by default on Windows 11).

bash
# Install some Linux GUI apps
sudo apt install -y gedit gimp vlc x11-apps

# Launch them — they appear as Windows windows!
gimp &
xclock &   # Classic X11 test

# Test audio
sudo apt install -y pulseaudio-utils
paplay /usr/share/sounds/alsa/Front_Left.wav
🪞
Lesson 21

Mirrored Networking

WSL gets the same IP as Windows. Ports are instantly accessible. VPN-aware. IPv6 native.

+15XP
Complete to earn

🚀 Enable Mirrored Mode

Add to C:\Users\YourName\.wslconfig:

.wslconfig
[wsl2]
networkingMode=mirrored
dnsTunneling=true

Then run wsl --shutdown and relaunch. Verify with:

bash
hostname -I         # Should match Windows IP
python3 -m http.server 8080 &
# Access localhost:8080 from Windows browser instantly
📦
Lesson 22

VHD Storage Management

Manage the virtual disk that stores your WSL filesystem — resize, compact and monitor it.

+15XP
Complete to earn

📊 Check Disk Usage

bash
# Total disk usage
df -h /

# What's using the most space?
du -sh /* 2>/dev/null | sort -rh | head -20

# Find large files
find / -size +500M -not -path "/proc/*" 2>/dev/null

# Clean apt cache
sudo apt clean && sudo apt autoremove -y

💨 Enable Sparse VHD (Windows 11)

PowerShell
# Sparse VHD automatically returns freed space to Windows
wsl --manage Ubuntu --set-sparse true
🔧
Lesson 23

Common Issues

Fast solutions to the most frequent WSL problems.

+20XP
Complete to earn

❌ WSL Won't Start

PowerShell (Admin)
wsl --shutdown
wsl --update
wsl

❌ Error 0x80370102 (Virtualization Disabled)

🖥️
Fix: Enable Virtualization in BIOS
Restart PC → Enter BIOS (usually F2/Del) → Find "Virtualization", "Intel VT-x" or "AMD-V" → Enable it → Save and reboot. Then run wsl --update.

❌ No Internet in WSL

bash
# Test connectivity
ping -c 3 8.8.8.8

# If ping works but DNS fails, fix resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
sudo chattr +i /etc/resolv.conf

# Or try switching to mirrored networking in .wslconfig

❌ Docker iptables Error

bash
# Switch to legacy iptables
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo service docker restart
📋
Lesson 24

Logs & Debugging

Find and read the right logs when things go wrong.

+15XP
Complete to earn

📋 Linux Logs

bash
# Kernel messages (including WSL-specific)
dmesg | tail -50

# systemd journal (if systemd enabled)
journalctl -xe
journalctl -u docker --since "10 minutes ago"

# WSL status overview
wsl --version
wsl --status
wsl -l -v

🪟 Windows Event Logs

PowerShell (Admin)
Get-WinEvent -LogName Microsoft-Windows-Lxss-Manager/Operational -MaxEvents 20 |
  Select-Object TimeCreated, Message | Format-List
🔄
Lesson 25

Reset & Repair

Nuclear options — when nothing else works. Use only as last resort.

+15XP
Complete to earn
💣
These Commands Delete Data
wsl --unregister deletes all files inside that distro. Always export a backup first: wsl --export Ubuntu C:\backup.tar.gz

🔄 Reset a Distro

PowerShell
# Back up first!
wsl --export Ubuntu C:\backup-$(Get-Date -Format yyyyMMdd).tar.gz

# Delete and reinstall
wsl --unregister Ubuntu
wsl --install -d Ubuntu

💣 Full WSL Reset

PowerShell (Admin)
# Disable WSL features
dism.exe /online /disable-feature /featurename:Microsoft-Windows-Subsystem-Linux
dism.exe /online /disable-feature /featurename:VirtualMachinePlatform

# Restart, then re-enable
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# Restart again, then
wsl --update
wsl --install
Reference

Command Cheatsheet

Every important WSL command, organized and copyable.

Install & Update
wsl --install
wsl --update
wsl --version
wsl --status
Distro Lifecycle
wsl -l -v
wsl -d <distro>
wsl --set-default <distro>
wsl -t <distro>
wsl --shutdown
wsl --unregister <distro>
Backup & Restore
wsl --export Ubuntu backup.tar.gz
wsl --import Ubuntu C:\WSL backup.tar.gz
wsl --manage <d> --set-sparse true
Interop Helpers
explorer.exe .
wslpath -w ~/path
echo "text" | clip.exe
code .
Network
ip addr show eth0
ip route show default
ss -tlnp
curl ifconfig.me
Disk & Storage
df -h /
du -sh * | sort -rh | head
sudo apt clean