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:
Restart your computer.Step 2: Install Distro¶
We support Ubuntu (stable) and Arch (via ArchWSL).
Step 3: Install Dotfiles¶
Follow the standard One-Line Bootstrap inside your new Linux terminal:
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):
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.
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:
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:
- WSL's built-in DNS (
generateResolvConf=true): Automatically syncs/etc/resolv.conffrom Windows DNS settings - systemd-resolved (
systemd=true): Linux's native DNS resolver that expects DHCP or manual configuration
Recommended Configuration (for systemd-enabled WSL):
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:
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:
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.