How to Use Linux on Windows: Windows Subsystem for Linux
Windows Subsystem for Linux (WSL) is a Windows feature that runs a real Linux distribution, bash and all, directly inside Windows. No dual boot, no separate virtual machine to babysit. On a current Windows 10 or 11 machine, the whole install boils down to one command and a restart, and I’ll walk through every step of it below.
I’m not writing this as a Windows convert who came around. I’m a Mac and bash person who got handed a Windows laptop for work, twice now at two different jobs, and Windows Subsystem for Linux is the only reason I didn’t have to relearn how to think in PowerShell.
Linux got me through undergrad on a ten-year-old Dell
Long before WSL was part of any job, Linux was part of survival. I ran Ubuntu on a 2011 Dell because I refused to pay for a new computer. The catch was that most of my assignments and labs were written assuming Windows, and I didn’t have it.
So I found the alternative. When a lab needed Windows, I spun up an EC2 instance and RDP’d into a Windows Server running on it, straight from my Ubuntu laptop, and did the assignment over that remote desktop connection to a machine sitting in some AWS data center. My professors got a finished Windows lab. My own laptop never ran Windows once.
That’s the part that makes this whole post funny in hindsight. Back then I ran Linux and reached across the network for Windows when a class demanded it. Now I run Windows for work and Linux runs inside it for everything that actually matters to me. Nobody ever asked which OS I’d pick given the choice. I just kept building the bridge from whichever side I was stuck on.
What Windows Subsystem for Linux actually is
Windows Subsystem for Linux solves a specific mismatch. Developers want Linux tools, and IT departments want to issue Windows machines. WSL runs a Linux distribution, Ubuntu by default, on top of Windows, and lets Linux and Windows tools call each other directly.
There have been two real versions, and mixing them up matters:
- WSL 1 was a compatibility layer. It translated Linux system calls into Windows kernel calls, with no real Linux kernel underneath. It left beta in the Fall Creators Update, October 2017.
- WSL 2, generally available with the Windows 10 May 2020 update, replaced that translation layer with an actual Linux kernel running inside a lightweight managed VM. Microsoft’s own comparison spells out the tradeoff plainly. WSL 2 gets full system call compatibility (the reason Docker works properly on it and never really did on WSL 1), but WSL 1 is faster for one specific thing, reading and writing files that live on the Windows side of the machine.
I lived that tradeoff without knowing its name. From 2017 to January 2021, I was an Identity and Access Management assistant at CSUN IT (California State University, Northridge), and the WSL install on that computer stayed on WSL 1 the entire time. It wasn’t a downgrade so much as nobody’s job to touch. It worked, so it stayed.
How to actually install WSL, step by step
Here’s exactly what to do, in order, the same steps that got Ubuntu running on my own Windows laptop.
1. Check you’re on a Windows version that supports it. You need Windows 10 version 2004 or later (Build 19041+), or Windows 11. If you’re not sure which build you’re on, a quick internet search shows you how to check it in a few seconds.
2. Open PowerShell as Administrator. Right-click the Start button, or search “PowerShell,” and choose “Run as administrator.” Every step below assumes that elevated prompt.
3. Run the install command.
wsl --install
That one line enables the Windows features WSL needs and installs Ubuntu, the default distro, for you. Want something else instead? wsl --install -d Debian installs Debian. wsl --list --online shows everything available to pick from.
4. Restart your machine when it asks. This isn’t optional. The features wsl --install just enabled need a reboot before Windows will actually load them.
5. Let Ubuntu finish setting up, then create your Linux user. After the restart, Ubuntu opens on its own and spends a minute decompressing files onto your machine. That only happens once. Every launch after this takes under a second. It’ll then ask you for a username and password for your Linux account. That’s separate from your Windows login, and it’s the account sudo will ask for from here on, so pick something you’ll actually remember.
6. Confirm it actually worked.
wsl --list --verbose
That prints every distro you have installed and which WSL version each one is running, 1 or 2. A fresh install lands on WSL 2 by default, which is the version doing the work in everything below.
7. Set a default distro and default version (optional), useful once you have more than one installed.
wsl --set-default Ubuntu
wsl --set-default-version 2
8. Get Windows Terminal, if it isn’t already on your machine. It ships with modern Windows 11 and is a free Microsoft Store download on Windows 10. It’s the one place that comfortably runs PowerShell, Command Prompt and your new Ubuntu shell in tabs, and it’s what I actually open every morning instead of hunting for Ubuntu in the Start menu.
That’s the whole install. No product key, no license screen, no partitioning to get wrong. Microsoft’s own install guide covers every flag if you want the exhaustive version. This is the version I actually needed.
One more thing worth knowing once you’ve got it running. New installs default to WSL 2, and Microsoft’s own guidance is to stay on it unless you hit one of a short list of exceptions, mostly serial-port access, strict memory limits, or files that must stay on the Windows side. That last one is basically the CSUN-era WSL 1 use case, just named properly.
What it actually looks like today
I typed wsl from a PowerShell prompt on my current work laptop while writing this, and here’s exactly what came back:
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.6.114.1-microsoft-standard-WSL2 x86_64)
System information as of Sun Sep 27 00:56:13 PDT 2026
System load: 2.65
Usage of /: 1.6% of 1006.85GB
Memory usage: 26%
Swap usage: 0%
Processes: 68
Users logged in: 2
That -microsoft-standard-WSL2 string in the kernel name is the tell. I’m on WSL 2 now, not the WSL 1 I ran without ever thinking about it at CSUN. One command took me from a Windows prompt to a full Linux system reporting its own load average, memory and swap, like it’s just another box on the network, because from its own point of view, it is one. That’s the part I actually find impressive, not that Windows tolerates Linux, but that on a machine whose Start menu says Windows, I end up living inside Linux more hours of the day than I live inside Windows itself.
What annoyed a Mac and bash person, and what fixed it
My current job, at San Diego Unified School District, put me back on a Windows laptop, under a year ago now. Same deal, no choice, company machine. Here’s what actually got in the way, and what I changed.
| The friction | What I did about it |
|---|---|
| PowerShell isn’t bash, and muscle memory doesn’t transfer | Live inside the WSL terminal for anything that isn’t Windows-specific, instead of fighting PowerShell into acting like a shell it isn’t |
| Ctrl vs Cmd, and copy-paste in the terminal never lands the way a Mac trains you to expect | Kept expectations low and let Windows Terminal’s own keybindings win, rather than trying to force Mac muscle memory onto Windows |
| Two filesystems, two PATHs, two sets of installed tools | Picked one home for a project (the Linux side) and stopped letting work drift across the boundary mid-task |
Projects living under /mnt/c/... were noticeably slower to work with from WSL |
Moved active projects into the Linux filesystem itself (/home/<user>/...), which is exactly what Microsoft’s own file-system guidance recommends |
That last one is the gripe with an actual receipt behind it. Microsoft’s file-systems documentation says plainly that if you’re working from a Linux command line, store your files on the Linux side, not on a mounted Windows drive under /mnt/c. I found that out the slow way before I found it in the docs, which tracks with how I learn most things.
The PATH confusion wasn’t unique to this job either. It showed up at CSUN too, two toolchains, two sets of expectations, and no shortage of “wait, which python is this” moments on both machines, years apart.
My setup: making WSL feel like home
Nothing exotic. Plain bash, no framework layered on top of it, with my own aliases and dotfiles carried over so the shell feels like the one I actually think in. vim is still where I actually write things. Changing operating systems was never going to be the thing that finally got me onto a mouse-driven editor. Windows Terminal is the thing I actually open, with Ubuntu set as the default profile so I never have to go looking for it. And for anything that benefits from seeing a whole project at once, VS Code’s WSL extension lets me run code . from inside the Linux filesystem and get a normal editor window, with the actual file access happening on the Linux side instead of across that slow bridge.
That’s the whole list, and none of it is impressive. It doesn’t need to be. The shell, the terminal, the editor, those are just how I get back to a Linux environment I actually like working in. Windows is the part I’m managing around, not the part I came here to enjoy.
Claude Code lives in that same WSL terminal, doing the actual work I’ve written about elsewhere, like keeping its day-to-day cost down. It doesn’t care that the OS underneath is technically Windows, and at this point, neither do I.
My virtual environments, pip, python3, Docker, basically my entire stack, lives on the Linux side. Type any of it into a bare Windows prompt and you get nothing back but a blank stare.
Claude Code is the one that actually catches me out, more often than I’d like to admit. Forget to switch into WSL first, type claude straight into a plain PowerShell prompt out of habit, and PowerShell has no idea what I’m talking about. It’s installed on the Linux side. Plain Windows has never heard of it.
A few commands worth having on day one
You don’t need to memorize much to get by. These are the ones I actually reach for.
wsl, typed from any Windows prompt, drops you straight into your default Linux distro. No hunting for Ubuntu in the Start menu.wsl --shutdown, run from PowerShell, restarts WSL cleanly if it’s ever acting up. Close your Ubuntu window first, run this, then reopen it.explorer.exe ., run from inside your WSL shell, opens your current Linux folder right in Windows File Explorer. Handy the moment you need to drag a file somewhere.wsl --updategrabs the newest WSL release from the Microsoft Store, no reinstalling anything.
That covers what I actually use day to day.
Where WSL still loses
Not everything about WSL earns its keep, and a few of its real limits are documented well enough by other people that I don’t need to be the first to say them, just to confirm I’ve actually run into every one.
- Memory. WSL 2 runs Linux inside a small virtual computer that lives inside your real one, and that virtual computer can end up using more and more of your machine’s memory the longer it stays open. Microsoft’s own comparison admits it, and people have been tracking it as an open issue on the WSL repo for years. If it ever gets out of hand, there’s a settings file called
.wslconfigwhere you can put a hard limit on how much memory WSL is allowed to use. WSL doesn’t do that for you on its own. - You’re still running Windows underneath. WSL doesn’t get you out of Windows Update’s own reboot schedule, its telemetry, or whatever security software your employer has running in the background. Windows Defender’s real-time scanning in particular has its own documented history of eating CPU during builds, on top of anything WSL itself is doing.
- Reading and writing files across the Windows-Linux boundary is genuinely bad. I already flagged
/mnt/cas slow above. The actual number is over 10x slower than WSL’s own native Linux side for anything with lots of small files, like anode_modulesfolder or a large git checkout. Every one of those files has to cross from Linux into Windows and back, and that round trip isn’t free.
None of that makes WSL a bad idea. It’s proof that WSL isn’t a magic trick. It’s Linux, running inside Windows, paying a real Windows tax to get there.
I still run a self-hosted GitHub Actions runner inside WSL, and it’s genuinely slow. GitHub-hosted runners and their 2,000 free minutes a month cover most of what I need, and I only fall back to the self-hosted one inside WSL once those minutes run out for the month. It works, it’s just noticeably slower than the hosted option, and it’s worth budgeting for that instead of assuming a self-hosted runner inside WSL is a free upgrade over paying for overage minutes.
I’ve written before about the eight-stage review pipeline that runs before anything I build merges, and GitHub-hosted runners are exactly what powers the CI stage of that. WSL didn’t make that pipeline faster. It just stayed out of its way.
The verdict: good enough, but Mac still wins
WSL is slower in general than working directly on Linux or on a Mac. I’ll say that plainly, because pretending otherwise would undercut everything above it. But it’s not close between WSL and plain Windows. If a company laptop is Windows, I’m running WSL on it every time, no exceptions, no second thoughts.
That’s the honest version, not “WSL fixed Windows,” just “WSL makes Windows tolerable enough that I stop noticing which OS I’m technically on.” And that itself says something. On a machine issued to run Windows, I spend more of my actual working hours inside Linux than inside Windows. Given a real choice, though, I’d still take a Mac, or the Ubuntu box that got me through undergrad, over either one.
If you’re stuck on a Windows machine for work, what’s actually kept you sane? WSL, a full Linux partition, or something else entirely?