Skip to Main content

Install WSL for Development and Fix Common Problems on Windows

WSL is one of the easiest ways to get a Linux development shell on Windows, but the first setup has a few sneaky corners. This guide covers the bits worth fixing early.

WSL removes a lot of friction when you want Linux tooling without leaving Windows behind. The installation is short, but a few follow-up steps make it much more pleasant for real development work, especially if you use Git, .NET, or large local project folders.

Installation

Install WSL

Run the following command to install WSL:

wsl --install

Restart Windows to complete the setup. When WSL starts for the first time, it will ask you to create a Linux username and password for your default account.

Update packages

Once the distro is ready, update the package list and install the latest updates:

sudo apt update && sudo apt upgrade -y

Install build tools and locale support

Run the following commands to install build tools:

sudo apt install -y build-essential pkg-config libssl-dev locales unzip
sudo locale-gen en_US.UTF-8

That is enough for many common CLI tools and source builds. If you later hit a package that still complains: WSL has invited you into the traditional Linux pastime of installing one more dependency.

Install the .NET SDK

If you use .NET inside WSL, start with Microsoft's distro-specific instructions because the package feed can vary by Ubuntu version:

On an Ubuntu-based WSL image, the final install step commonly looks like this:

sudo apt-get update && sudo apt-get install -y dotnet-sdk-10.0

Then verify the SDK is available:

dotnet --info

Open your WSL folder in File Explorer

To open your WSL project in Windows File Explorer, use the following command:

explorer.exe .

That is a handy way to move between terminal work and GUI tools without memorising the hidden network path to your distro.

Git Setup

If you want Git commands inside WSL to reuse the credentials you already signed into on Windows, set that up early. It saves a lot of repetitive prompts later.

Install Git on Windows

Ensure the latest version of Git is installed on Windows.

Reuse Windows credentials from WSL

Then configure Git Credential Manager from the Linux side. This assumes Git for Windows is installed and reasonably current.

git config --global credential.helper "/mnt/c/Program Files/Git/mingw64/bin/git-credential-manager.exe"

If Git still refuses to use the saved credentials, close all WSL windows and shut it down from the Windows side:

wsl --shutdown

Reopen WSL after shutting it down.

Troubleshooting

Reclaim space from a growing WSL virtual disk

WSL disks tend to grow quietly and stay large even after you delete files. Before compacting the virtual disk from Windows, clean up what you can from inside Linux:

sudo apt clean
sudo apt autoremove -y
sudo fstrim -v -a

If you use Docker, large package caches, or temporary build folders inside WSL, clean those up first as well. Compacting works better after the filesystem has already released as much space as possible.

If the Optimize-VHD PowerShell command is not available, enable Hyper-V management tools from an elevated PowerShell window:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

Windows may ask for a restart. After that, run this elevated PowerShell script to compact every Store-managed WSL disk it can find, using Optimize-VHD command:

function Compress-WSLDisks {
  $disks = Get-ChildItem `
    -Path "$env:LOCALAPPDATA\Packages\*\LocalState\ext4.vhdx" `
    -ErrorAction SilentlyContinue

  if (-not $disks) {
    Write-Host 'No Store-managed WSL disks were found.'
    return
  }

  wsl --shutdown

  foreach ($disk in $disks) {
    $before = [math]::Round($disk.Length / 1GB, 2)
    Write-Host "Compacting $($disk.FullName)"
    Write-Host "Before: $before GB"

    Optimize-VHD -Path $disk.FullName -Mode Full

    $updatedDisk = Get-Item -LiteralPath $disk.FullName
    $after = [math]::Round($updatedDisk.Length / 1GB, 2)
    Write-Host "After:  $after GB"
  }
}

Compress-WSLDisks

This script targets the default Store-backed disk location. If you imported a distro to a custom path, compact that .vhdx file directly instead.

Fix TLS certificate errors behind a corporate proxy

If your company runs a security gateway that inspects HTTPS traffic (Cisco Umbrella, Zscaler, Palo Alto, and similar), downloads inside WSL can fail with a certificate error even though the same site works fine in your Windows browser. A typical message looks like this:

SSL routines:tls_post_process_server_certificate:certificate verify failed: unable to get local issuer certificate

The gateway terminates the TLS connection and re-signs it with its own certificate authority (CA). Windows already trusts that CA because IT pushed it through group policy, but a fresh WSL distro has never seen it, so verification fails.

You can confirm the interception by inspecting the certificate a host actually serves. The issuer will be your security vendor rather than the real site:

echo | openssl s_client -connect release-assets.githubusercontent.com:443 -servername release-assets.githubusercontent.com 2>/dev/null | grep -iE "subject=|issuer=|verify return code"

If the issuer= line names your corporate gateway and you see verify return code: 20 (unable to get local issuer certificate), the fix is to copy the trusted CAs from Windows into WSL.

Export the trusted roots from Windows

Run this in Windows PowerShell. It exports every trusted root CA, including the one your gateway uses, into a single PEM bundle:

Get-ChildItem Cert:\LocalMachine\Root | ForEach-Object {
  "-----BEGIN CERTIFICATE-----"
  [Convert]::ToBase64String($_.RawData, 'InsertLineBreaks')
  "-----END CERTIFICATE-----"
} | Out-File -Encoding ascii "$env:USERPROFILE\windows-roots.crt"

Import the bundle into WSL

From WSL, copy the file into the system trust store and refresh it. Replace <YourWindowsUser> with your Windows account name:

sudo cp "/mnt/c/Users/<YourWindowsUser>/windows-roots.crt" /usr/local/share/ca-certificates/windows-roots.crt
sudo update-ca-certificates

A successful run reports at least 1 added:

Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

After this, tools that use the system certificate store, such as curl, git, and most native applications, will validate the inspected connections correctly.

Tools that bundle their own certificates

Some runtimes and tools ship their own CA list and ignore the system store. Bun and curl can both surface UNABLE_TO_GET_ISSUER_CERT_LOCALLY (sometimes shown as unable to get local issuer certificate) even after the import step. Point them at the system bundle with an environment variable:

# Node.js, Bun, and other Node-compatible runtimes
export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt

# Python requests / certifi
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

Add those lines to your ~/.bashrc or ~/.zshrc to make them permanent. If your gateway rotates its CA, re-export from Windows and run update-ca-certificates again.

References