Setting up Windows - samhocevar/... GitHub Wiki

Install Windows

Create installation media

From Windows:

Boot the installer

⚠️ make sure to disconnect network cable to avoid using a Microsoft account

In the standard installer:

  • Language settings
    • Language to install: English (United Kingdom)
    • Time and currency format: English (Ireland) (to get the € symbol and 24-hour time format)
  • Keyboard settings
    • Keyboard or input method: US
  • Select Image
    • Choose Windows 11 Pro

Bypass Microsoft account requirement (documentation from https://www.tomshardware.com/how-to/install-windows-11-without-microsoft-account):

  • after the first reboot, open a terminal with Shift+F10 and type OOBE\BYPASSNRO. This will reboot again.
  • after the second reboot, open a terminal and type ipconfig /release to disable Internet.

⚠️ do not create the main Windows account yet, choose something like “admin” first

After Windows is installed

Mount volumes

If there are extra drives on the system, use mountvol to mount them to directories instead of drive letters.

📝 This action is permanent and stored into the registry if the drive is not disconnected.

Create main user with alternate profile directory

(TODO)

Configure sane behaviour

# Set the system clock to UTC instead of local time
# ⚠️ This is highly recommended if the same machine will also run Linux
$key = "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
Set-ItemProperty "$key" RealTimeIsUniversal 1

# Enable dark mode by default
# ⚠️ this should be done per-user
$key = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"
Set-ItemProperty "$key" AppsUseLightTheme 0
Set-ItemProperty "$key" SystemUsesLightTheme 0

# Enable developer mode
$key = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
Set-ItemProperty "$key" AllowDevelopmentWithoutDevLicense 1

# Enable sudo
# 📝 Possible values are 1: open new window; 2: disable input; 3: inline
# Documented at https://learn.microsoft.com/en-us/windows/advanced-settings/sudo/
$key = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo"
Set-ItemProperty "$key" Enabled 3

# Make File Explorer more usable
$key = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer"
Set-ItemProperty "$key\Advanced" DontPrettyPath 1
Set-ItemProperty "$key\Advanced" Hidden 1
Set-ItemProperty "$key\Advanced" HideDrivesWithNoMedia 0
Set-ItemProperty "$key\Advanced" HideFileExt 0
Set-ItemProperty "$key\Advanced" ShowSuperHidden 1
Set-ItemProperty "$key\Advanced" TaskbarAl 0
Set-ItemProperty "$key\CabinetState" FullPath 1

# Show the “run as different user” entry in start menu
$key = "HKCU:\Software\Policies\Microsoft\Windows\Explorer"
if (!(Test-Path "$key")) { New-Item -Force "$key" }
Set-ItemProperty "$key" ShowRunAsDifferentUserInStart 1

# Disable Visual Studio package cache and installer sounds
# 📝 Documented at https://learn.microsoft.com/en-us/visualstudio/install/configure-policies-for-enterprise-deployments
$key = "HKLM:\SOFTWARE\Policies\Microsoft\VisualStudio\Setup"
if (!(Test-Path "$key")) { New-Item -Force "$key" }
Set-ItemProperty "$key" KeepDownloadedPayloads 0
Set-ItemProperty "$key" DisableSound 1

# Disable UAC sound, it gets incredibly annoying
$key = "HKCU:\AppEvents\Schemes\Apps\.Default\WindowsUAC\.Current"
Set-ItemProperty "$key" "(Default)" ""

Optional but probably a good thing

# Update PowerShell documentation
Update-Help

# Disable SearchIndexer.exe
# Call sc.exe instead of sc which is a PowerShell builtin
sc.exe config WSearch start= disabled
sc.exe stop WSearch

Software installation

Most software can now be installed using WinGet.

# Install WinGet and ensure the package source is sane
# 📝 Method suggested here: https://stackoverflow.com/a/78235229/111461
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
Add-AppxPackage -Path https://cdn.winget.microsoft.com/cache/source.msix
winget upgrade --all

# Uninstall some common Microsoft bloat
# ⚠️ this should be done per-user
winget uninstall "Copilot"
winget uninstall "Microsoft 365 Copilot"
winget uninstall "Microsoft Bing"
winget uninstall "Microsoft News"
winget uninstall "Microsoft Web Experience Pack"

# Install development tools and languages
winget install --scope machine -e Microsoft.VisualStudio.2022.Professional
winget install --scope machine -e vim.vim Microsoft.VisualStudioCode
winget install --scope machine -e Python.Python.3.13 GoLang.Go zig.zig
winget install --scope machine -e Microsoft.NuGet JRSoftware.InnoSetup oleg-shilo.mkshim
winget install --scope machine -e Microsoft.Sysinternals.Suite 7zip.7zip

# Install Git
# 📝 MinGit is a lot lighter than Git Bash, but doesn’t have Git LFS or most of the MINGW tools
winget install --scope machine -e Git.MinGit GitTools.GitVersion
winget install --scope machine -e GitHub.GitLFS --skip-dependencies
# ⚠️ As of 23 Jul 2025, GitHub.GitLFS installs Git.Git which we do not want
# (see https://github.com/microsoft/winget-pkgs/issues/276985)
winget uninstall --scope machine Git.Git

# Install security and privacy tools
winget install --scope machine -e IDRIX.VeraCrypt WireGuard.WireGuard WiresharkFoundation.Wireshark
winget install --scope machine -e WinFsp.WinFsp

# Various quality of life tools and productivity software
winget install --scope machine -e AntibodySoftware.WizTree
winget install --scope machine -e SamHocevar.WinCompose
winget install --scope machine -e GIMP.GIMP.3 Inkscape.Inkscape KDE.Krita
winget install --scope machine -e BlenderFoundation.Blender Tiled.Tiled
winget install --scope machine -e Mozilla.Thunderbird Mozilla.Firefox Google.Chrome
winget install --scope machine -e VideoLAN.VLC OBSProject.OBSStudio

# Game stores
winget install --scope machine -e Valve.Steam EpicGames.EpicGamesLauncher Itchio.Itch
# 📝 Optionally, move the game locations to a different drive or mount point and create symlinks; for instance:
if (0) {
    cmd /c mklink /j "${env:ProgramFiles(x86)}/Steam/steamapps" "C:/Shared/games/steam"
    cmd /c mklink /j "${env:ProgramFiles}/Epic Games" "C:/Shared/games/epic"
}

# Communication software
# ⚠️ These cannot be installed system-wide, probably because they manage their own update mechanism
winget install -e Discord.Discord SlackTechnologies.Slack
winget install -e Telegram.TelegramDesktop OpenWhisperSystems.Signal
winget install -e 9NKSQGP7F2NH # This is WhatsApp from the MS Store

# Install and configure MSYS2 for all users
# 📝 The AllUsers=true argument is for the Start Menu items and is specific to the Qt Installer they use
# ⚠️ One day machine scope installation might work, see https://github.com/microsoft/winget-pkgs/issues/276996
$msys = "${env:ProgramFiles}/MSYS2"
winget install --scope machine -e MSYS2.MSYS2 -l "$msys"

Configure installed software

$msys = "${env:ProgramFiles}/MSYS2"

# Share home directory between Windows and MSYS2
& "$msys/usr/bin/sh.exe" -c "/usr/bin/sed -i -e 's/^\\(db_home:\\).*/\\1 env/' /etc/nsswitch.conf"
# Enable native symlinks for all MSYS2 flavours
& "$msys/usr/bin/sh.exe" -c "/usr/bin/sed -i -e 's/^[# ]*\\(MSYS=winsymlinks:\\).*/\\1nativestrict/' /*.ini"
# Inherit Windows path for all MSYS2 flavours
& "$msys/usr/bin/sh.exe" -c "/usr/bin/sed -i -e 's/^[# ]*\\(MSYS2_PATH_TYPE=\\).*/\\1inherit/' /*.ini"

# Emulate sticky bit on /tmp in MSYS2
icacls "$msys/tmp" /reset /T /C
icacls "$msys/tmp" /inheritance:d
icacls "$msys/tmp" /grant "Users:(OI)(CI)(M)" /T /C

# Add shims for Vim executables
# 📝 Vim installation path varies with the version so we try to retrieve it in the registry
# 📝 We hope that one day WinGet supports shims (see https://github.com/microsoft/winget-cli/issues/361)
$vimroot = $(Split-Path (Get-ItemPropertyValue HKLM:\SOFTWARE\Vim\Gvim "path"))
mkshim "${env:ProgramFiles}/WinGet/Links/vi.exe" "${vimroot}/vim.exe"
mkshim "${env:ProgramFiles}/WinGet/Links/vim.exe" "${vimroot}/vim.exe"
mkshim "${env:ProgramFiles}/WinGet/Links/gvim.exe" "${vimroot}/gvim.exe"

Install WSL

# Enable Hyper-V features, including PowerShell extensions
# 📝 Documented at https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/get-started/install-hyper-v
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All -NoRestart

⚠️ A reboot is required

# Create a shared drive
New-VHD -Path ext4.vhdx -SizeBytes 10G -Fixed

# ⚠️ Cannot really attach the drive, because WSL2 misses many features
# Instead, create a junction to e.g.
# ${env:LOCALAPPDATA}/Packages/TheDebianProject.DebianGNULinux_76v4gfsz19hv4/LocalState

wsl --install Debian
wsl sudo apt install zsh ssh vim bc unzip zip 7zip dos2unix
wsl sudo apt install make automake autoconf libtool pkg-config patch diffutils

Visual Studio

Suggested workloads:

  • .NET desktop development
  • Desktop development with C++
  • WinUI application development
  • Mobile development with C++
  • Game development with C++
  • Linux, Mac, and embedded development with C++

Windows Terminal

Open ${env:LOCALAPPDATA}/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json and add the following section:

{
    "commandline": "%ProgramFiles%/MSYS2/msys2_shell.cmd -defterm -here -no-start -ucrt64",
    "guid": "{31cb0223-1770-4bd5-9b91-5641dd78fdad}",
    "hidden": false,
    "icon": "%ProgramFiles%/MSYS2/ucrt64.ico",
    "name": "MSYS2 (UCRT64)",
    "startingDirectory": "%USERPROFILE%"
}

Tweaks

For USB drives, especially SSDs, that are not meant to be removed: open devmgmt.msc and set Removal Policy to “Better Performance”.

General housekeeping

MSYS2 pacman cache cleanup:

  • install pacman-contrib
  • remove all cached packages except for the last version: paccache -k1 -r
  • remove all cached packages for uninstalled software: paccache -k0 -u -r

Change a USB device’s friendly name to avoid confusion: https://superuser.com/a/549079/71253

Remove huge files in System Volume Information: https://superuser.com/a/1761943/71253