Setup Windows 10 for Linux System Engineer - nqngo/talks GitHub Wiki
Windows is now pretty great for Linux Development. This documents the process for setup Windows and using script automation when possible. This article assume this is on a fresh copy of Windows or development laptop.
Prerequisite
Open a new Windows PowerShell
terminal in Administrator Mode.
(Optional) Upgrading to latest Windows Build
If you are running a Windows Build older than 19041, update to the latest Service Pack version.
# update-windows-10-to-latest-build.ps1
# Exit if we are not using Windows 10
if ((Get-WmiObject -class Win32_OperatingSystem).Version -notmatch '^10\.') {
Write-Host 'ERROR: Not Windows 10.' -ForegroundColor Red
Exit 1
}
# Install the update
Write-Output "WARNING: Updating to the latest Windows Service Pack..."
$dir = 'C:\_Windows_FU\packages'
mkdir $dir
$webClient = New-Object System.Net.WebClient
$url = 'https://go.microsoft.com/fwlink/?LinkID=799445'
$file = "$($dir)\Win10Upgrade.exe"
$webClient.DownloadFile($url,$file)
Start-Process -FilePath $file -ArgumentList '/quietinstall /skipeula /auto upgrade /copylogs $dir'
# Clean up
sleep 10
Remove-Item "C:\_Windows_FU" -Recurse -Force -Confirm:$false
Write-Host "Windows 10 Service Upgrade Finished! Restarting..." -ForegroundColor Yellow
Restart-Computer -Confirm
(Optional) Trigger Windows Store Updates
Run the following script to trigger Update All
on Windows Store
. Unfortunately at this stage, the method is async and do not reported successfully status update.
# update-windows-store-apps.ps1
Get-CimInstance -Namespace "Root\cimv2\mdm\dmmap" -ClassName "MDM_EnterpriseModernAppManagement_AppManagement01" |
Invoke-CimMethod -MethodName UpdateScanMethod
Setup WSL2
The Windows Subsystem for Linux lets developers run a GNU/Linux environment -- including most command-line tools, utilities, and applications -- directly on Windows, unmodified, without the overhead of a traditional virtual machine or dualboot setup.
Microsoft documented the process for installing WSL here: https://docs.microsoft.com/en-us/windows/wsl/install
On your Powershell console, run:
wsl --install
[!WARNING] You must be running Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11. If your windows version is lower, run cumulative update for Windows to get the latest Service Pack.
Alternatively, you can automate this process by:
# w10-wsl-install.ps1
# Exit if wsl is already installed
try {
wsl -l | Out-Null
}
Catch [System.Management.Automation.CommandNotFoundException] {
Write-Host 'ERROR: WSL already installed.' -ForegroundColor Red
Exit 1
}
# Install WSL2 if we are on build 19041+
if ((Get-WmiObject -class Win32_OperatingSystem).BuildNumber -gt 19041) {
wsl --install
} else {
Write-Output "WARNING: Unsupported Windows 10 version. Updating to the latest Windows Service Pack"
}
Install packages via PowerShell
At the time of writing, I would recommend using Chocolatey over Windows built-in Winget as Chocolatey has significant more packages support than Winget.
To start, install Chocolatey:
# install-chocolatey.ps1
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
Install packages:
# install-dev-packages.sh
choco feature enable -n=allowGlobalConfirmation
# Utilities
choco install dotnet-runtime
choco install 7zip
choco install powertoys
choco install greenshot
choco install microsoft-windows-terminal # Update WindowsStore if error
# Fonts
choco install nerd-fonts-droidsansmono --pre
# Hashicorp
choco install terraform
choco install packer
# (Optional) Otherwise, use minikube inside WSL2
choco install minikube
choco install kubernetes-helm
# CLI tools
choco install git
choco install gnupg
choco install win-gpg-agent
choco install gsudo
choco install gh
# IDE
choco install vscode
Once gsudo
is installed. We can dropped out of privileged shell and only escalated once needed.
(Optional) Use DroidSans Mono Nerd Fonts in Windows Terminal
To install the Nerd Fonts we fetched through Chocolatey, run the following in an unprivileged Powershell:
# set-font-windows-terminal.ps1
$fontFace = "DroidSansMono Nerd Font"
$fontSize = 11
$settingsJsonPath = "$($env:LOCALAPPDATA)\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
$fontProperties = @{
face=$fontFace;
size=$fontSize
}
$settings = Get-Content $settingsJsonPath -Raw | ConvertFrom-Json
ForEach ($profile in $settings.profiles.list) {
$font = [PSCustomObject]$fontProperties
$profile | Add-Member -NotePropertyName font -NotePropertyValue $font -Force
$profile.font = $font
}
$settings | ConvertTo-Json -depth 100 | Out-File $settingsJsonPath
Write-Host "SUCCESS: Setting all Windows Terminal profile font to $fontFace ($fontSize)" -ForegroundColor Green
Install VSCode Extension
Install VSCode extension via Powershell:
# install-vscode-extensions.ps1
# Hashicorp
code --install-extension 4ops.packer
code --install-extension hashicorp.terraform
code --install-extension infracost.infracost
# Scripting
code --install-extension github.copilot
code --install-extension ms-vscode.powershell
# Kubernetes
code --install-extension Tim-Koehler.helm-intellisense
code --install-extension ms-kubernetes-tools.vscode-kubernetes-tools
Configure GPG for Windows and WSL2
gnupg
is a must if you are looking into signing code commits and storing password through pass in WSL2. It also allows us to use Yubikey as the ssh-agent to securely login via hardware security token. I used win-gpg-agent to provide GPG relay to WSL2 from Windows.
[NOTE!] While
gnupg
installed viaChocolatey
should work out of the box, I found that its Qt-basedpinentry
can be buggy and might not pass the PIN through.win-gpg-agent
pinentry
program works better from my experience.
win-gpg-agent
is installed from our previous Chocolatey install script. It will then needed to be configured as followed:
# gsudo configure-win-gpg-agent.ps1
$agentPath="$env:ChocolateyInstall\lib\win-gpg-agent\tools\agent-gui.exe"
# Configure startup
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "GPG Agent" -Value $agentPath
# Stop the native ssh-agent service, gpg-agent will take over
Stop-Service ssh-agent
Set-Service -StartupType Disabled ssh-agent
In WSL2 instance, install socat
and soft link sorelay.exe
to WSL:
$ sudo apt install socat
$ mkdir -p ~/winhome/.wsl
$ ln -s /mnt/c/ProgramData/chocolatey/lib/win-gpg-agent/tools/sorelay.exe /home/$user/winhome/.wsl/sorelay.exe
Setup https://raw.githubusercontent.com/rupor-github/win-gpg-agent/main/docs/win-gpg-agent-relay script:
curl https://raw.githubusercontent.com/rupor-github/win-gpg-agent/main/docs/win-gpg-agent-relay -o $HOME/.local/bin/win-gpg-agent-relay
chmod +x $HOME/.local/bin/win-gpg-agent-relay
Add the following .wsl_gpg_agent.sh
script to your $HOME:
#!/bin/bash
# detect what we have
if uname -a | grep -q Microsoft; then
# WSL 1 could use AF_UNIX sockets from Windows side directly
if [ "${WSL_AGENT_HOME}" ]; then
export GNUPGHOME=${WSL_AGENT_HOME}
export SSH_AUTH_SOCK=${WSL_AGENT_HOME}/S.gpg-agent.ssh
fi
elif uname -a | grep -q microsoft; then
# WSL 2 needs help from socat/sorelay
${HOME}/.local/bin/win-gpg-agent-relay start
export SSH_AUTH_SOCK=${HOME}/.gnupg/S.gpg-agent.ssh
fi
Source the script from .bashrc or your startup profile:
source "$HOME/.wsl_gpg_agent.sh"