Skip to content

Windows & WSL2 Guide

Windows is a first-class citizen in this dotfiles repository. We advocate for a hybrid workflow: Windows for GUI/Gaming, WSL2 for Development.

Architecture

graph TD
    A[Windows Host] -->|Hyper-V| B[WSL2 VM]
    B --> C[Arch/Debian/Ubuntu]
    A -->|VS Code Remote| C
    A -->|Windows Terminal| C
    C -->|Run .exe| A

1. Installation

Step 1: Enable WSL

Open PowerShell as Administrator:

wsl --install
Restart your computer.

Step 2: Install Distro

We support Ubuntu (stable) and Arch (via ArchWSL).

wsl --install -d Ubuntu

Step 3: Install Dotfiles

Follow the standard One-Line Bootstrap inside your new Linux terminal:

curl -fsSL https://raw.githubusercontent.com/jerdaw/dotfiles/main/scripts/bootstrap | bash


2. Configuration

Global Settings (.wslconfig)

Located at %UserProfile%\.wslconfig on Windows. Controls VM resources.

Recommended Defaults (handled by mise-tasks/setup/provision/windows/install.ps1):

[wsl2]
memory=16GB              # Limit RAM usage
processors=4             # Limit CPU cores
vmIdleTimeout=-1         # Prevent WSL from sleeping (Windows 11)

Distro Settings (/etc/wsl.conf)

Located inside Linux. Controls distro behavior.

Recommended Defaults (handled by dot_wslconfig task):

[boot]
systemd=true

[interop]
appendWindowsPath=true  # Allow running .exe from Linux


3. Integration & Interop

Clipboard

We alias pbcopy and pbpaste to use Windows clipboard tools transparently.

echo "Hello Windows" | pbcopy   # Copies to Windows clipboard
pbpaste > linux_file.txt        # Pastes from Windows clipboard

Opening Files

Use open to launch the default Windows application for a file.

open report.pdf   # Opens in Edge/Acrobat
open .            # Opens Windows Explorer in current dir

Browser

We use wslview (from wslu package) to open links in your default Windows browser.


4. Performance Tips

❌ The /mnt/c Trap

NEVER store your project files in /mnt/c/Users/You/Projects. File I/O across the VM boundary is slow (P9 filesystem).

✅ The \\wsl$ Way

Store all code inside the Linux filesystem: ~/projects. Access it from Windows Explorer via \\wsl$\Ubuntu\home\you\projects.

Windows Defender

Add an exclusion for your distribution’s package folder to speed up I/O. %LOCALAPPDATA%\Packages\Canonical...


5. Troubleshooting Common Issues

Clock Drift

Symptom: git or apt fails with SSL errors; time is wrong. Fix: sudo hwclock -s

DNS Resolution Failures

Symptom: ping google.com fails with "Temporary failure in name resolution", but ping 8.8.8.8 works.

Diagnosis:

# Check if DNS resolution works
getent hosts google.com

# Check systemd-resolved status
resolvectl status

# Check resolv.conf
cat /etc/resolv.conf

Fix for systemd-enabled WSL (recommended): 1. Ensure /etc/wsl.conf has:

[network]
generateResolvConf = true
2. Restart WSL: wsl --shutdown (from PowerShell) 3. WSL will auto-generate /etc/resolv.conf from Windows DNS

Why this happens: With systemd=true in WSL, systemd-resolved runs but may lose upstream DNS servers during network changes (VPN, sleep/wake). Letting WSL manage DNS (generateResolvConf=true) syncs with Windows automatically.

"Access Denied" on Windows Files

Symptom: Cannot modify files on /mnt/c. Fix: Ensure the file isn't open in a Windows program (like Word or Excel) which locks it.


6. DNS Troubleshooting Deep Dive

Understanding WSL DNS Architecture

WSL with systemd has two DNS management systems that can conflict:

  1. WSL's built-in DNS (generateResolvConf=true): Automatically syncs /etc/resolv.conf from Windows DNS settings
  2. systemd-resolved (systemd=true): Linux's native DNS resolver that expects DHCP or manual configuration

Recommended Configuration (for systemd-enabled WSL):

# /etc/wsl.conf
[boot]
systemd=true

[network]
generateResolvConf=true  # Let WSL manage DNS

This dotfiles repository uses this approach because: - ✅ Automatically syncs with Windows DNS changes - ✅ Works seamlessly with VPN connections/disconnections - ✅ Handles network adapter changes (WiFi ↔ Ethernet) - ✅ No manual DNS server configuration needed

Common DNS Failure Patterns

Pattern 1: Works After Reboot, Fails Later

Symptom: DNS works after wsl --shutdown but breaks after network changes.

Root Cause: generateResolvConf=false with systemd-resolved losing upstream DNS servers.

Permanent Fix:

# Automated fix (recommended)
mise run fix:wsl-dns

# Then from PowerShell
wsl --shutdown

Pattern 2: "Temporary failure in name resolution"

Diagnosis:

# Check if IP connectivity works
ping 8.8.8.8              # Should work

# Check DNS resolution
ping google.com            # Fails

# Check systemd-resolved status
resolvectl status          # Shows "Current Scopes: none" = BAD

Immediate Workaround (temporary):

# Manually add DNS servers
sudo tee /etc/resolv.conf >/dev/null <<EOF
nameserver 1.1.1.1
nameserver 8.8.8.8
EOF

Permanent Fix:

# Automated fix (recommended)
mise run fix:wsl-dns

# Or manually
cd ~/repos/dotfiles
chezmoi apply
# Then: wsl --shutdown (from PowerShell)

Pattern 3: Mirrored Networking + DNS Issues

If using networkingMode=mirrored in .wslconfig:

# ~/.wslconfig (Windows side)
[wsl2]
networkingMode=mirrored
dnsTunneling=true          # CRITICAL for mirrored mode

Verify:

# Should show Windows host DNS
cat /etc/resolv.conf

# Should match Windows DNS servers
ipconfig /all              # From PowerShell

Prevention Checklist

Run the health check after any network changes:

mise run doctor

The doctor check will flag DNS issues and suggest fixes.

Pattern 4: Tailscale Hostname Resolution

Symptom: ssh hostname@hostname works in Windows PowerShell but fails in WSL with "Could not resolve hostname: Name or service not known".

Root Cause: Tailscale's MagicDNS is not available in WSL when Tailscale runs only on the Windows host. Windows can resolve Tailscale hostnames, but WSL cannot.

Recommended Fix (without installing Tailscale in WSL):

# Add Tailscale hosts to /etc/hosts
# Get the IP from PowerShell: tailscale status
echo "100.x.x.x hostname" | sudo tee -a /etc/hosts

Why Not Install Tailscale in WSL? Running Tailscale in both Windows and WSL simultaneously can cause conflicts and connection issues. It's simpler and more reliable to: - Keep Tailscale running on Windows host - Add frequently-used Tailscale hosts to /etc/hosts in WSL - Use IPs directly when needed: ssh user@100.x.x.x

Alternative: If you need full MagicDNS support and dynamic hostname resolution, you can install Tailscale inside WSL and disable the Windows Tailscale client. However, this is not recommended for most users.