DEV Community

Cover image for The ultimate WSL2 setup (updated 2024)
Peter Repukat
Peter Repukat

Posted on • Edited on

The ultimate WSL2 setup (updated 2024)

This is a crosspost originally from my own blog


Last Update: 10/23/2024

Ever wondered how to seamlessly blend Windows and Linux in your daily workflow?

My friends and colleagues frequently ask about my WSL setup - both for personal projects and professional work.

I used to direct them to an old blog post of mine, but that always required a massive wall of explanatory text, since things have evolved significantly.

So here is my personal "Ultimate WSL2 Setup"

TL;DR

for everyone that doesn't feel like reading my gibberish:

Setup

Terminal: Your Gateway to Command Line Bliss

Before diving into WSL and shell configurations, let's get you set up with a proper terminal emulator. The landscape has evolved significantly, and your options are much better than they were a few years ago.

The Windows Terminal has matured into a fantastic choice with an impressive feature set. The best part? It's blazing fast! They've even added a sweet quake-mode feature recently, making it a worthy replacement for the old "conhost.exe".

While Windows Terminal has become my daily driver, it does have a few limitations. If you need advanced features like auto-start in hidden-quake mode or separate always-on-top settings for quake-mode and normal-mode instances, ConEmu remains the most feature-rich alternative - just be prepared for slightly slower performance.

Fonts

Next up, let's talk typography. You'll want fonts with extensive glyph support (icons) - I recommend checking out nerd-fonts. While Windows lacks an official all-in-one installer, you can either use your preferred Windows package manager or cherry-pick specific fonts as I did

Windows Sudo: Trust Me, You'll Want This

Here's a game-changer: gsudo, essentially bringing sudo to Windows.

On Windows 11, it's as simple as running winget install gsudo in an elevated PowerShell.

Once installed, you can elevate any Windows process/command with a simple gsudo prefix.

WSL

I've fallen in love with Arch Linux's minimalist approach, which fits perfectly within WSL's ecosystem. While Arch isn't officially supported, several excellent distro launchers make it possible. I've had great success with ArchWSL, which has proven reliable even in professional settings.

For a basic installation, you can refer to their excellent guide here

If you've never used WSL before or start with a fresh Windows install, use Microsoft's guide to install WSL, but install ArchWSL from their GitHub page, instead of any other distro from the Microsoft store.

Systemd

Recent WSL2 versions finally support Systemd, enabling things like docker without the pesky  "Docker for Windows"-App.

Although it's not enabled by default...

To activate it, add this to /etc/wsl.conf:

[boot]
systemd=true
Enter fullscreen mode Exit fullscreen mode

File system gotchas

While recent Windows versions provide built-in access to Linux files, some compatibility quirks remain. I prefer mapping WSL files as a network drive using \\wsl.localhost\ - simple and effective.

From the Linux side, you can project file permissions and metadata to NTFS, though it requires configuration.

This enables neat tricks like symlinking your Windows-generated SSH folder, eliminating redundant key and config management.

Here's my battle-tested /etc/wsl.conf configuration:

# Includes enabling Systemd from above
[boot]
systemd=true

# Enable extra metadata options by default
[automount]
enabled = true
root = /mnt/
options = "metadata,rw,umask=22,fmask=11"
mountFsTab = false

# Enable DNS  even though these are turned on by default, we’ll specify here just to be explicit.
[network]
generateHosts = true
generateResolvConf = true

[interop]
enabled=true
appendWindowsPath=true
Enter fullscreen mode Exit fullscreen mode

USB Support: Connecting the Physical World

Another feature that is missing from WSL out of the box is support for USB devices.

However, recently (at time of writing) M$ did put some work into it, and posted about a way to make it happen.

That's great news for anyone who's into Arduino or similar stuff or even car-hacking, as I personally find that that kinda stuff is just easier to set up on Linux than on Windows.

Basically, just install usbipd-win...

winget install --interactive --exact dorssel.usbipd-win
Enter fullscreen mode Exit fullscreen mode

For Arch users, that's all you need!

From any elevated command prompt, you can manage USB devices with usbipd wsl list and usbipd wsl attach --busid XX.

With gsudo, you can run these commands directly from WSL:

cmd.exe /c gsudo usbipd wsl list
cmd.exe /c gsudo usbipd wsl attach --busid 4-4
Enter fullscreen mode Exit fullscreen mode

WSL-Open: Seamless integration

Want to make your WSL experience even smoother?

wsl-open is a must-have tool. It lets you use Linux's standard xdg-open command to open files and links with native Windows applications. Installation is a breeze via npm:

sudo npm install -g wsl-open
Enter fullscreen mode Exit fullscreen mode

But there is also a non-npm installation described on their GitHub page, if you're not into node.

Port Fowards: Reaching the Outside World

While WSL normally forwards network ports to Windows automatically (though it occasionally hiccups 🤷‍♂️), external access remains challenging.

This can be frustrating when you need SSH access or want to quickly share files via a temporary web server.

Here's a PowerShell script that solves this limitation, allowing direct port forwarding to WSL (also available on GitHub):

# WSL2 network port forwarding script v1
#   for enable script, 'Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser' in Powershell,
#   for delete exist rules and ports use 'delete' as parameter, for show ports use 'list' as parameter.
#   written by Daehyuk Ahn, Aug-1-2020

# Display all portproxy information
If ($Args[0] -eq "list") {
    netsh interface portproxy show v4tov4;
    exit;
}

# If elevation needed, start new process
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
  # Relaunch as an elevated process:
  Start-Process powershell.exe "-File",('"{0}"' -f $MyInvocation.MyCommand.Path),"$Args runas" -Verb RunAs
  exit
}

# You should modify '$Ports' for your applications
$Ports = (667)

# Check WSL ip address
#wsl /bin/sh -c "ip route get 1 | grep 1. | awk '{print \`$3}'" | Set-Variable -Name "WSL"
#wsl hostname -i | Set-Variable -Name "WSL"
$WSL = wsl bash -c "ifconfig eth0 | grep 'inet ' | awk '{print \`$2}'"
echo $WSL
$found = $WSL -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
if (-not $found) {
  echo "WSL2 cannot be found. Terminate script.";
  exit;
}

# Remove and Create NetFireWallRule
Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock';
if ($Args[0] -ne "delete") {
  New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $Ports -Action Allow -Protocol TCP;
  New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $Ports -Action Allow -Protocol TCP;
}

# Add each port into portproxy
$Addr = "0.0.0.0"
Foreach ($Port in $Ports) {
    iex "netsh interface portproxy delete v4tov4 listenaddress=$Addr listenport=$Port | Out-Null";
    if ($Args[0] -ne "delete") {
        iex "netsh interface portproxy add v4tov4 listenaddress=$Addr listenport=$Port connectaddress=$WSL connectport=$Port | Out-Null";
    }
}

# Display all portproxy information
netsh interface portproxy show v4tov4;

# Give user to chance to see above list when relaunched start
If ($Args[0] -eq "runas" -Or $Args[1] -eq "runas") {
  Write-Host -NoNewLine 'Press any key to close! ';
  $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
}
Enter fullscreen mode Exit fullscreen mode

Pro tip: Avoid using port 22 for your SSH server, as the native Windows SSH server will intercept these connections.

[Optional] Custom Kernel: For the Power Users

While most users won't need a custom kernel, it's essential for specific use cases like running SocketCAN for car hacking. Here's how to build and install your own kernel:

#get kernel version
uname -r
  5.10.60.1-microsoft-standard-WSL2

# get matching version, this is mine
wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/linux-msft-wsl-5.10.60.1.tar.gz

#extract it (change to your kernel version)
tar -xf linux-msft-wsl-5.10.60.1.tar.gz

# build linux/modules

# change to the folder tar extracted too, yours might be different
cd  WSL2-Linux-Kernel-linux-msft-wsl-5.10.60.1/
cat /proc/config.gz | gunzip > .config
make prepare modules_prepare -j $(expr $(nproc) - 1)

# select your drivers/modules here
make menuconfig -j $(expr $(nproc) - 1)
make modules -j $(expr $(nproc) - 1)
sudo make modules_install
make -j $(expr $(nproc) - 1)
sudo make install

# copy it to windows drive, change <yourwindowsloginname> to your windows users 
cp vmlinux /mnt/c/Users/<yourwindowsloginname>/

#create this file
vim /mnt/c/Users/<yourwindowsloginname>/.wslconfig

#with these contents
[wsl2]
kernel=C:\\Users\\<yourwindowsloginname>\\vmlinux

# exit wsl
wsl.exe --shutdown
Enter fullscreen mode Exit fullscreen mode

Missing something?

Am I missing something?
Let me know!

Top comments (1)

Collapse
 
evadeflow profile image
Evade Flow

Thanks for this! I really wanted to get SocketCAN working on WSL2, and this post was like an express train straight to that destination. I can tell the other tips about USB support, port forwards, wslopen, etc are also going to be super helpful. 🙇‍♂️