Windows

Updated in December 2023.

Installation

Creating a Installation USB

You can download Windows 10 directly from the Microsoft website. Choose a USB drive of at least 8GB for the tool to format and create a bootable installer.

If the error 715-123130 appears, try changing your browser or downloading through a VPN in the USA.

If you download the ISO, verify the hash:

PS > Get-FileHash .\Win11_22H2_EnglishInternational_x64v1.iso

Algorithm       Hash
---------       ----
SHA256          F115CD6B31734BC091BC94B964D5AD43984285BF229503481E2F7EF94AB7140E

I recommend Rufus for burning the image. It has some very interesting features.

Partitioning

A typical Windows installation creates 4 partitions:

  • EFI: 100 MB
  • MSR: 16 MB
  • Windows
  • Recovery: 500 MB to 650 MB

The value you should enter in the graphical installer is the sum of all these partitions. If you want your C: to show exactly 250 GB, you should use something slightly larger than 256616 MB (100 + 16 + 250 * 1024 + 500).

For more control over the sizes, you can partition the disk via command line. Press Shift + F10 and use diskpart:

diskpart
list disk
select disk 0
clean
convert gpt
create partition efi size=1024
format quick fs=fat32 label="System"
assign letter="S"
create partition msr size=16
create partition primary size=256000
format quick fs=ntfs label="Windows"
assign letter="W"
create partition primary size=700
format quick fs=ntfs label="Recovery"
assign letter="R"
set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
gpt attributes=0x8000000000000001
list volume
exit

In this example, an EFI partition with 1 GB and a Recovery partition with 700 MB are created.

An EFI with at least 300 MB is recommended for those who dual boot. Linux mounts this partition as /boot and stores files used by the bootloader, including compressed versions of the kernel and drivers (vmlinuz).

If you already have an EFI partition formatted in FAT32 before starting the installation, Windows will use it instead of creating a new one.

If you realize you need to increase the EFI partition after Windows is already installed, check out Macrorit’s Partition Expert. The free portable version can easily resize and move partitions.

The 16MB MSR (Microsoft Reserved) partition can be restored by Windows itself (create partition msr) or by using the code 0c01 in cgdisk.

Privacy options

A privacy screen appears on the first boot. Uncheck Find my device, Inking & Typing, Advertising ID, Diagnostic data, Tailored experiences, and any other options to uncheck during installation.

After starting the system, go to Settings » Privacy. I uncheck almost all options. The only app that needs access to my camera (which is covered) is Skype.

Group Policy Editor

Run gpedit.msc.

  • Web search

    Go to Local Computer Policy » Computer Configuration » Administrative Templates » Windows Components » Search and enable the option “Do not allow web search”.

  • BitLocker with PIN

    Navigate to Computer Configuration » Administrative Templates » Windows Components » BitLocker Drive Encryption » Operating System Drives and enable Require Additional Authentication at Startup and Allow enhanced PINs for startup.

  • Disable Skype’s Meet Now feature

    Go to User Configuration » Administrative templates » Start Menu and Taskbar and enable the policy Remove the Meet Now icon.

Regedit

  • Disable Cortana and Bing

    Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Windows Search and create a new DWORD named ConnectedSearchUseWeb and assign it a value of 0.

    Navigate to HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Search and create two new DWORDs with a value of 0: AllowSearchToUseLocation and BingSearchEnabled.

  • Use UTC in the clock (useful for dual-booting)

    Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation and create a new DWORD named RealTimeIsUniversal with a value of 1.

  • Show/Hide desktop icons

    This can be done through the graphical interface, so I do not recommend doing it through regedit.

    Computer: {20D04FE0-3AEA-1069-A2D8-08002B30309D}
    User Files: {59031a47-3f72-44a7-89c5-5595fe6b30ee}
    Control Panel: {5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}
    Network: {F02C1A0D-BE21-4350-88B0-7367FC96EF3C}
    Recycle Bin: {645FF040-5081-101B-9F08-00AA002F954E}
    

Example:

reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel /V {20D04FE0-3AEA-1069-A2D8-08002B30309D} /T REG_DWORD /D 0x0 /F
reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu /V {20D04FE0-3AEA-1069-A2D8-08002B30309D} /T REG_DWORD /D 0x0 /F
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel /V {20D04FE0-3AEA-1069-A2D8-08002B30309D} /T REG_DWORD /D 0x0 /F
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu /V {20D04FE0-3AEA-1069-A2D8-08002B30309D} /T REG_DWORD /D 0x0 /F
  • Does not show recent files
reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer /V ShowRecent /T REG_DWORD /D 0x0 /F
  • Show user folder in File Explorer navigation (quick access)
reg add HKCU\SOFTWARE\Classes\CLSID\{59031a47-3f72-44a7-89c5-5595fe6b30ee} /V System.IsPinnedToNameSpaceTree /T REG_DWORD /D 0x1 /F

Computer Name

Navigate to Control Panel\System and Security\System. On the line with the computer name, click on Change settings and change the computer name.

Windows Update

Update everything and restart the computer.

The latest update may not yet be available through Windows Update, but it can be installed manually: https://www.microsoft.com/en-us/software-download/windows10.

Drivers

  • Kensington Works
  • Nvidia
  • Manufacturer’s website

Encryption

  • BitLocker

    After updating Windows, enable BitLocker on the C:/ drive. Save the recovery key in a secure location (not on the computer itself, of course).

  • VeraCrypt

    It is an open-source alternative that can be used to encrypt entire partitions or create containers. Later on, I will show how to install it using Chocolatey.

Windows Features

Go to Control Panel\Programs » Turn Windows features on or off.

  • Enable “Virtual Machine Platform”
  • Enable “Windows Hypervisor Platform” (required for Docker).
  • Enable “Windows Sandbox”
  • Enable “Windows Subsystem for Linux”
  • Enable “Hyper-V” (for virtual machines)

Power

Navigate to Control Panel\Hardware and Sound\Power Options\Create a Power Plan and create a power plan based on High Performance with the following options (in advanced power settings):

  • Turn off hard disk after
    • On battery: 30 Minutes
    • Plugged in: Never
  • Sleep
    • Sleep after
      • On battery: 300 Minutes
      • Plugged in: Never
  • Power buttons and lid
    • Lid close action
      • On battery: Do nothing
      • Plugged in: Do nothing
    • Power button action
      • On battery: Sleep
      • Plugged in: Do nothing
  • Display
    • Turn off display after
      • On battery: 20 Minutes
      • Plugged in: 30 Minutes

In Control Panel\Hardware and Sound\Power Options\System Settings, uncheck the option Turn on fast start-up.

Inactivity Lock

  • Screen Saver settings » Blank » 3 min » On resume, display log-on screen

Uninstall unnecessary programs

In Add or Remove programs, uninstall what you won’t use.

Disable annoying messages

Go to Control Panel\System and Security\Security and Maintenance\Change Security and Maintenance settings.

Uncheck the option to receive messages about Windows Backup.

Chocolatey

Install following the most current instructions at https://chocolatey.org/install.

In PowerShell as Admin:

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
choco install -y `
  7zip `
  calibre `
  discord `
  ditto `
  Firefox `
  git `
  GoogleChrome `
  greenshot `
  jellyfin-media-player `
  nerd-fonts-Hack `
  obs-studio `
  slack `
  spotify `
  steam `
  telegram `
  transgui `
  vlc `
  vscode `
  wireguard
choco install -y `
  ack `
  bleachbit `
  clonespy `
  Cmder `
  curl `
  darktable `
  dbeaver `
  digikam `
  docker-desktop `
  eartrumpet `
  Everything `
  FreeDownloadManager `
  gimp `
  gnupg `
  google-drive-file-stream `
  imagemagick `
  irfanview `
  jre8 `
  mariadb `
  microsoft-teams `
  miniconda3 `
  neovim `
  nerd-fonts-CascadiaCode `
  nerd-fonts-FiraCode `
  nodejs `
  notepadplusplus `
  okular `
  postman `
  powershell-core `
  powertoys `
  restic `
  rsync `
  sourcetree `
  sql-server-management-studio `
  thunderbird `
  transmission `
  treesizefree `
  vb-cable `
  vcxsrv `
  veracrypt `
  voicemeeter-banana `
  winscp

Update Chocolatey

  • List outdated packages:

    choco outdated
    
  • Update Chocolatey first:

    choco upgrade chocolatey
    
  • Update all packages:

    choco upgrade all -y
    

PowerShell

Windows 10 and 11 come with version 5.1 installed, but the newest version is available on GitHub and can be installed through Chocolatey or winget.

winget search Microsoft.PowerShell
winget install --id Microsoft.Powershell --source winget
> $PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      1

Execution Policy

PowerShell has the following options to restrict script execution:

  • Restricted: Does not run scripts. Use PowerShell only in interactive mode.
  • AllSigned: Runs only scripts signed by a trusted publisher.
  • RemoteSigned: Downloaded scripts need to be signed.
  • Unrestricted: All scripts can be run.

I will configure using the RemoteSigned option:

Set-ExecutionPolicy RemoteSigned

Oh My Posh

Oh My Posh is a Terminal theme that is especially good for PowerShell.

The easiest way to install it is with Winget:

winget install JanDeDobbeleer.OhMyPosh -s winget

Then configure PowerShell to start Oh My Posh:

notepad $PROFILE

And paste the following:

oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/powerlevel10k_lean.omp.json" | Invoke-Expression
Set-PSReadlineOption -EditMode vi -BellStyle None

These commands will configure PowerShell to use the powerlevel10k_lean theme in vi mode. Other themes can be previewed with the Get-PoshThemes command and on the official website.

The notepad $PROFILE command edits the $profile.currentusercurrenthost. If you want to configure for other hosts and users, edit the appropriate file:

$profile.currentusercurrenthost
C:\Users\Julio\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

$profile.currentuserallhosts
C:\Users\Julio\Documents\PowerShell\profile.ps1

$profile.alluserscurrenthost
C:\Program Files\PowerShell\7\Microsoft.PowerShell_profile.ps1

$profile.allusersallhosts
C:\Program Files\PowerShell\7\profile.ps1

Office

I share a Microsoft 365 Family subscription with 5 other people. I consider it very worthwhile because in addition to Office, each person also gets 1 TB of OneDrive. Furthermore, we often find promotions for a prepaid 1-year Personal subscription, which can be converted into 9 months of Family.

The installer with all Office 365 programs can be downloaded from your Microsoft account. There you choose the language and version (32 or 64-bit).

It is also possible to install each program separately from the Microsoft Store, but I do not recommend it.

Emails

I like to use Thunderbird as my email client.

  1. To save space, uncheck the option to sync folders. This way, only the headers will be downloaded;
  2. Set it to minimize to the taskbar;
  3. Register your PGP key to sign emails;
  4. Use a master password to protect the passwords and keys saved in Thunderbird (file key4.db): Tools » Options » Privacy & Security » use a master password.

To set up emails that use Two-factor authentication, you can use a specific app password or set up initially without a password and then change it to OAuth2.

Calendar

For most people, leaving the email tab open in the browser and enabling notifications should be enough, but I use multiple calendars and like to keep track of them in one place and receive event alerts on the desktop.

The default Windows app is fully integrated with the system and allows you to view events directly in the taskbar and receive native notifications, but since I already use Thunderbird for emails, I also prefer to configure it to sync my calendars.

Display calendar only (view only)

The link to your Google calendar can be obtained as follows:

  1. Go to Google Calendar settings (https://calendar.google.com/calendar/u/0/r/settings);
  2. Settings for my calendars
  3. Select the calendar;
  4. Integrate calendar;
  5. Secret address in iCal format

Paste this link into Thunderbird: File » New » Calendar » On the Network » iCalendar (ICS).

The calendar will be marked as read-only.

To view events on the main screen: View » Today Pane » Show Today Pane.

Bi-directional synchronization (view & edit)

The add-ons Lightning and Provider for Google have this functionality, but you can also configure Thunderbird to use CalDav as follows:

  • Google: create a specific password at https://myaccount.google.com/apppasswords.
  • Zoho: 1. Create a specific password at Zoho Accounts » Security » App Passwords » Application-Specific Passwords » Generate New Password. 2. Activate CalDav at Settings » Calendar » Synchronize » CalDAV. 3. Get the Calendar ID at Settings » Calendars » My Calendars In Thunderbird, go to File » New » Calendar » On the Network » CalDAV.
  • Username: your@email.com
  • Google Location: https://www.google.com/calendar/dav/your@email.com/events
  • Zoho Location: https://calendar.zoho.com/caldav/**Calendar ID**/events

Languages

I like to keep my notebook in English, but it’s good to add other languages like Portuguese.

Settings » Languages » Preferred Languages » Add a preferred language.

Add/remove languages via PowerShell

PS > $langs = Get-WinUserLanguageList

PS > $langs
LanguageTag     : en-GB
Autonym         : English (United Kingdom)
EnglishName     : English
LocalizedName   : English (United Kingdom)
ScriptName      : Latin
InputMethodTips : {0809:00020409}
Spellchecking   : True
Handwriting     : False
PS > $langs.Add('de-DE')

PS > $langs
LanguageTag     : en-GB
Autonym         : English (United Kingdom)
EnglishName     : English
LocalizedName   : English (United Kingdom)
ScriptName      : Latin
InputMethodTips : {0809:00020409}
Spellchecking   : True
Handwriting     : False

LanguageTag     : de-DE
Autonym         : Deutsch (Deutschland)
EnglishName     : German
LocalizedName   : German (Germany)
ScriptName      : Latin
InputMethodTips : {0407:00000407}
Spellchecking   : True
Handwriting     : False

PS > Set-WinUserLanguageList $langs -Force
PS > $langs.Remove(($langs | Where-Object LanguageTag -like 'de-DE'))
True

PS > $langs
LanguageTag     : en-GB
Autonym         : English (United Kingdom)
EnglishName     : English
LocalizedName   : English (United Kingdom)
ScriptName      : Latin
InputMethodTips : {0809:00020409}
Spellchecking   : True
Handwriting     : False

PS > Set-WinUserLanguageList $langs -Force

Ghost keyboard bug

Even in Germany, I use English (United Kingdom) as the system language and format. For some unknown reason, Windows insists on adding the German keyboard to the keyboard list.

To make matters worse, it does not appear in Regedit (Computer\HKEY_USERS\.DEFAULT\Keyboard Layout\Preload) or in the language and region options.

It is necessary to manually add it just to be able to remove the German keyboard from the list.

This can also be done via PowerShell:

$langs = Get-WinUserLanguageList
$langs[0].InputMethodTips.Add('0809:00000407')
Set-WinUserLanguageList $langs -Force
$langs[0].InputMethodTips.Remove('0809:00000407')
Set-WinUserLanguageList $langs -Force

Check the code in Regedit (Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language).

ID Tag Language Location
0x0416 pt-BR Portuguese Brazil
0x0816 pt-PT Portuguese Portugal
0x0409 en-US English United States
0x0809 en-GB English United Kingdom
0x0c0A es-ES Spanish Spain
0x0407 de-DE German Germany
0x1000 en-150 English Europe
0x1000 en-DE English Germany

Complete table: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c

Additional Clock

I have been communicating a lot with people from Australia and Norway. Since the time zone is quite different, I like to have an additional clock.

Go to Date & Time » Add clocks for different time zones and set up the new clock.

Customization

  • Wallpaper

    In Settings » Personalization, choose a background. I usually set it to Solid color black.

  • Colors

    Default app mode: Dark

  • Lock screen

    Disable showing apps on the lock screen and background on the sign-in screen.

  • Fonts

    Install a Nerd Font.
    I recommend Hack NF. Unzip the package, select all “Windows Compatible” fonts, right-click, and choose the Install or Install for all users option.

    Install Google Noto Fonts to avoid issues with unavailable characters (displayed as rectangles). Prefer the hinted version.

  • Show/Hide icons on the desktop

    Themes » Desktop Icon Settings. I like to keep This PC, Recycle Bin, and User folder.

  • Taskbar

    Remove all unnecessary items from the taskbar. Hide the search bar.

  • Disable programs that start with the system

    Open the task manager and disable programs that start with the system.

  • File Explorer

    Open File Explorer. Select View » Options » Change folder and search options. In the View tab, check/uncheck the following options:

    • Always show menus
    • Display the full path in the title bar
    • Show hidden files, folders, and drives
    • Hide extensions for known file types
    • Hide protected operating system files
  • Remove OneDrive from quick access

    [HKEY_CLASSES_ROOT\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}]
    "System.IsPinnedToNameSpaceTree"=dword:00000000
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}]
    "System.IsPinnedToNameSpaceTree"=dword:00000000
    
  • Default Apps

    • Music player: VLC
    • Photo viewer: IrfanView
    • Video player: VLC
    • Web browser: Firefox

    I also like to associate programs with extensions:

    • .txt → Notepad++
  • Chrome and Firefox

    Sync the browsers. Copy extension settings like uMatrix, if you have it.

  • Swap Esc with CapsLock

    It is possible to do it through Regedit, SharpKeys, PowerToys, and many others.

    • Regedit

      Save the following code as caps_swapescape.reg and run it:

      Windows Registry Editor Version 5.00
      
      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
      "Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,3a,00,01,00,01,00,3a,00,00,00,00,00
      

      A mapping consists of a 32-bit integer (two 16-bit scancodes each) in little-endian format.

      (03,00,00,00) → Indicates that 3 integers will come (96 bits = 24 hex digits) (01,00) → Escape (3a,00) → CapsLock

      • SharpKeys

        Caps Lock (00_3A) → Escape (00_01) Escape (00_01) → Caps Lock (00_3A)

      • PowerToys Enable Keyboard Manager » remap a key

Desktops

Swipe up with four fingers on the touchpad to bring up the option to create new desktops. I like to use 2 desktops.

Terminal

I like Cmder and Windows Terminal (available in the Microsoft Store). They are highly customizable. An important change is setting the font. I recommend Hack NF.

In Terminal (settings.json):


    "actions": [
        {
            "command": {
                "action": "copy",
                "singleLine": false
            },
            "keys": "ctrl+c"
        },
        {
            "command": "paste",
            "keys": "ctrl+shift+v"
        },
        {
            "command": "find",
            "keys": "ctrl+shift+f"
        },
        {
            "command": {
                "action": "splitPane",
                "split": "auto",
                "splitMode": "duplicate"
            },
            "keys": "alt+shift+d"
        },
        {
            "command": {
                "action": "sendInput",
                "input": "\u001b[13;2u"
            },
            "keys": "shift+enter"
        },
        {
            "command": {
                "action": "sendInput",
                "input": "\u001b[13;5u"
            },
            "keys": "ctrl+enter"
        },
        {
            "command": {
                "action": "sendInput",
                "input": "\u001b[13;6u"
            },
            "keys": "ctrl+shift+enter"
        },
        {
            "command": {
                "action": "sendInput",
                "input": "\u001b[32;2u"
            },
            "keys": "shift+space"
        },
        {
            "command": {
                "action": "sendInput",
                "input": "\u001b[32;5u"
            },
            "keys": "ctrl+space"
        },
        {
            "command": {
                "action": "sendInput",
                "input": "\u001b[32;6u"
            },
            "keys": "ctrl+shift+space"
        }
    ]

"defaultProfile": "{2c4de342-38b7-51cf-b940-2309a097f518}",

    {
        "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}",
        "hidden": false,
        "name": "Ubuntu",
        "fontFace": "Hack NF",
        "source": "Windows.Terminal.Wsl"
    },

    {
        "guid": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
        "hidden": false,
        "name": "PowerShell",
        "fontFace": "Hack NF",
        "source": "Windows.Terminal.PowershellCore"
    }

I change the paste command from ctrl+v to ctrl+shift+v to avoid breaking visual mode in vim.

Sandbox

For application testing, especially from dubious sources, it is recommended to use an isolated system: sandboxes or virtual machines.

For cases where it is not necessary or desirable to persist installations and configurations and the current version of Windows works, a sandbox is more practical than VMs. You don’t need to download images, it opens faster, takes up less disk space, etc.

Sandboxing can be done with programs like Sandboxie, however, Windows 10 Professional already comes with this feature natively, just needs to be activated.

The setup is very simple and the performance is good. Windows Sandbox uses Windows Containers technology, which in turn uses Hyper-V.

The Sandbox can be activated in Windows Features or with the following command in PowerShell:

Enable-WindowsOptionalFeature -Online -FeatureName "Containers-DisposableClientVM"

The configuration is done via XML files with the extension .wsb, like the following:

<Configuration>
  <VGpu>Disable</VGpu>
  <Networking>Disable</Networking>
  <MappedFolders>
    <MappedFolder>
      <HostFolder>C:\Share</HostFolder>
      <SandboxFolder>C:\Share</SandboxFolder>
      <ReadOnly>true</ReadOnly>
    </MappedFolder>
  </MappedFolders>
  <AudioInput>Disable</AudioInput>
  <VideoInput>Disable</VideoInput>
  <ProtectedClient>Enable</ProtectedClient>
  <PrinterRedirection>Disable</PrinterRedirection>
  <ClipboardRedirection>Disable</ClipboardRedirection>
  <MemoryInMB>8192</MemoryInMB>
  <LogonCommand>
    <Command>explorer.exe C:\Share</Command>
  </LogonCommand>
</Configuration>

This example starts a sandbox in protected mode, with 8 GB of RAM, read access to the C:\Share folder, and no access to network, microphone, webcam, printer, or desktop.

Virtualization: Hyper-V

Microsoft Sandbox is great for quick tests and running portable applications, but it does not cover the use case where persisting system modifications is necessary. In these cases, we should use virtual machines.

If you have a powerful server, it may be worth installing a virtual machine manager like Proxmox VE and using VMs for remote access. Depending on the situation, deploying a VM in the cloud is also a good idea.

For local installations on Windows, there are several hypervisor options, which can be of two types:

  • Type 1 Hypervisor:
    • Bare-metal, native
    • Accesses hardware directly
    • Better performance
    • Examples: VMware ESXi (VMware vSphere), Microsoft Hyper-V, Oracle VM, Citrix Hypervisor
  • Type 2 Hypervisor:
    • Hosted
    • Runs on the operating system
    • Easier to manage
    • Examples: VMware Fusion, VMware Workstation Pro, Oracle VM VirtualBox

VMware is said to have the most features, but I have been using Hyper-V that comes with Windows Pro mainly due to cost.

Linux, FreeBSD, and Windows can be installed on Hyper-V. One detail is that virtualized Windows also requires a license.

Tips:

  • Prefer using Generation 2.
  • Enable TPM: Security » Enable Trusted Platform Module
  • Create checkpoints (snapshots) before any changes
  • Offline installation (Windows 11):
    • Press Shift+F10 to open the terminal
    • Run C:\Windows\System32\oobe\BypassNRO.cmd
    • Click “I don’t have internet”
    • Click “Continue with limited setup”
  • In enhanced session mode, it is possible to copy and paste files between host and VM
  • Virtual disks “.vhdx” can be mounted to share files. Remember to unmount them before starting the VMs.
  • Activate Guest services

Nvidia Graphics Card on Hyper-V

Updated in Jan/2023. Using Windows 11.

Due to a security issue, Microsoft has disabled the “RemoteFX vGPU” option that allowed multiple VMs to share a GPU.

In Windows Server, there is an option to allocate a GPU entirely to a VM, known as GPU passthrough via Discrete Device Assignment (DDA). However, only Enterprise GPUs like Nvidia Quadro work with this feature.

The current solution is GPU Paravirtualization/GPU Partitioning. Refer to the following links for more information:

WSL2

After enabling “Windows Subsystem for Linux” in Windows Features, additional configuration is required.

Tip: much of what I wrote in the article about Arch also applies to Ubuntu on WSL.

  1. Install the kernel update

  2. Update WSL, if necessary

    wsl --update
    
  3. Set WSL2 as default: wsl --set-default-version 2

  4. Install Ubuntu

    • Option 1: from the Microsoft Store

    • Option 2: via command line

      cd ~\Downloads
      curl.exe -L -o ubuntu-2204.appx https://aka.ms/wslubuntu2204
      Add-AppxPackage .\ubuntu-2204.appx
      

      Run the file ~\Downloads\ubuntu-2204.appx. A message will appear stating that Ubuntu is already installed and a launch button to start Ubuntu.

  5. Check if the WSL version is 2: wsl --list --verbose

    If your version is 1, run wsl --set-version Ubuntu 2.

  6. [Optional] Move the image from C: to Z:

VHDs (virtual hard disks) in WSL2 are saved in C:\Users\[user]\AppData\Local\Packages\[distro]\LocalState\[distroPackageName]. Example: C:\Users\Julio\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\ext4.vhdx.

It is possible to move the image and redirect the path through Regedit, but there is a safer way using the function to export and import images:

Z:
mkdir Z:\WSL
wsl --export Ubuntu Z:\WSL\Ubuntu.tar
wsl --unregister Ubuntu
wsl --import Ubuntu Z:\WSL\ Z:\WSL\Ubuntu.tar
ubuntu.exe config --default-user julio
rm Z:\WSL\Ubuntu.tar
  1. Adjust the locales

    sudo nvim /etc/locale.gen
    sudo locale-gen
    
  2. Do not add Windows folders to the $PATH

    Add the following lines to the file /etc/wsl.conf:

    [interop]
    appendWindowsPath = false
    

    This significantly improves autocomplete performance on the command line, as accessing the Windows file system is very time-consuming.

    It is still possible to start programs from WSL, just use the full path or add symlinks in a folder that is already in the $PATH.

    See https://learn.microsoft.com/en-us/windows/wsl/wsl-config#interop-settings

  3. Enable Systemd

Feature available since WSL version 0.67.6.

Some programs (Snap, Flatpak, microk8s) depend on Systemd.

Add the following lines to the file /etc/wsl.conf:

[boot]
systemd=true

Restart WSL: wsl.exe --shutdown.

  1. Configure memory

    WSL2 runs on Hyper-V. By default, half (or 80% in new builds) of the machine’s memory is allocated. This value can be changed in the file C:\Users\julio\.wslconfig:

    wsl --shutdown
    notepad "$env:USERPROFILE/.wslconfig"
    
    [wsl2]
    memory=16GB
    swap=0
    processors=4
    

    Check with the free command in Linux.

    Notes:

    • Do not set a very high value, as what is allocated to Linux cannot be used by Windows.
    • To release memory, run echo 1 >> /proc/sys/vm/drop_caches as root.
    • The .wslconfig file must be saved as UTF-8 without BOM.
    • The swap is saved in %USERPROFILE%\AppData\Local\Temp\swap.vhdx
  2. Add additional repositories (PPAs):

    PPAs (Personal Package Archive) are additional repositories to Ubuntu’s repositories. Many of them are from official maintainers.

    • Neovim:
    sudo add-apt-repository ppa:neovim-ppa/unstable
    sudo apt update
    
    • Git
    sudo add-apt-repository ppa:git-core/ppa
    sudo apt update
    
  3. Update the system

    sudo apt update && sudo apt upgrade
    
  4. Install programs available via repositories:

    Basics:

    sudo apt install \
      ack \
      curl \
      ffmpeg \
      git \
      gitk\
      jq \
      make \
      neovim \
      p7zip-full \
      renameutils \
      rsync \
      sshfs \
      tree \
      wget \
      zsh \
      oathtool
    

    LaTeX:

    sudo apt install \
      latexmk \
      texlive-lang-portuguese \
      texlive-xetex
    

    Dependencies to compile Python:

    sudo apt install \
      build-essential \
      libbz2-dev \
      libffi-dev \
      liblzma-dev \
      libncursesw5-dev \
      libreadline-dev \
      libsqlite3-dev \
      libssl-dev \
      libxml2-dev \
      libxmlsec1-dev \
      llvm \
      tk-dev \
      xz-utils \
      zlib1g-dev
    
  5. Clone dotfiles (https://github.com/jbsilva/dotfiles) and create links to configuration files

    cd ~
    ln -s dotfiles/.zsh
    ln -s dotfiles/.zshrc
    ln -s dotfiles/.gitconfig-global
    ln -s dotfiles/.gitconfig-wsl .gitconfig
    ln -s dotfiles/.p10k.zsh
    ln -s dotfiles/.config
    
  6. Install programs from other sources:

    The Ubuntu repository does not always have the latest versions of packages. Alternatives:

    • PPAs
    • Snap
    • Flatpak
    • Appimage
    • .deb packages
    • Pre-compiled executables
    • Asdf
    • Cargo
    • Compile source code

    Asdf:

    git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1
    

    Mambaforge:

    wget https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh
    bash Mambaforge-Linux-x86_64.sh
    

    Flatpak (enable Systemd first):

    sudo apt install flatpak gnome-software-plugin-flatpak gnome-software
    
    flatpak remote-add --if-not-exists --user flathub https://flathub.org/repo/flathub.flatpakrepo
    
    flatpak update
    

    Hugo:

    CGO_ENABLED=1 go install --tags extended github.com/gohugoio/hugo@latest
    

    or

    HUGO_LATEST="0.121.1"
    wget -qO- https://github.com/gohugoio/hugo/releases/download/v${HUGO_LATEST}/hugo_extended_${HUGO_LATEST}_linux-amd64.tar.gz | tar xvz hugo -C ~/bin/
    

    or

    asdf plugin add hugo
    HUGO_LATEST=$(asdf list-all hugo | tail -1)
    asdf install hugo extended_$HUGO_LATEST
    asdf global hugo extended_$HUGO_LATEST
    

    Zellij:

    ZELLIJ_LATEST=0.39.2
    wget -qO- https://github.com/zellij-org/zellij/releases/download/v${ZELLIJ_LATEST}/zellij-x86_64-unknown-linux-musl.tar.gz | tar xvz zellij -C ~/bin/
    

    Yt-dlp:

    python -m pip install -U --pre yt-dlp
    

    or

    mkdir -p ~/bin
    wget -O ~/bin/yt-dlp https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux
    yt-dlp --update-to nightly
    

    ExifTool:

    ExifTool is a very useful program to keep my photo library organized.

    mkdir -p ~/bin
    EXIFTOOL_LATEST=12.70
    wget -qO- https://exiftool.org/Image-ExifTool-${EXIFTOOL_LATEST}.tar.gz | tar xvzf - -C ~/bin/
    mv ~/bin/Image-ExifTool* ~/bin/ExifTool
    ln -s ~/bin/ExifTool/exiftool ~/bin/exiftool
    
  7. Set default shell: chsh -s $(which zsh)

Compress WSL2 image

Compressing the image can save some MBs.

  • In WSL2:

    # apt autoremove && apt autoclean && apt clean
    # fstrim /
    
  • In PowerShell:

     > Get-AppxPackage -Name "*Ubuntu*" | Select PackageFamilyName
       PackageFamilyName
       -----------------
       CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc
    
    > wsl --shutdown
    > optimize-vhd -Path "C:\Users\Julio\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\ext4.vhdx" -Mode full
    

X server

No longer needed in newer WSL versions.

Install VcXsrv and allow it through the firewall (Windows Defender). Check the option Disable access control.

export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0

Note: the best way to make clipboard work in Neovim is with win32yank.exe. It is installed along with Neovim for Windows, but can also be installed manually:

mkdir ~/bin
export PATH=$HOME/bin:$PATH

wget https://github.com/equalsraf/win32yank/releases/latest/download/win32yank-x64.zip
unzip -p win32yank-x64.zip win32yank.exe > ~/bin/win32yank.exe
chmod +x ~/bin/win32yank.exe
rm -f win32yank-x64.zip

Copy to the + register using "+y. Alternatively, use :set clipboard=unnamedplus in Neovim.

Docker Desktop with WSL2

This option is the simplest, but only free for personal, academic, open-source, or small business use (less than 250 employees AND less than $10 million in annual revenue).

Download Docker Desktop (I download it through Chocolatey). Check the options Use the WSL 2 based engine and Expose daemon on tcp://localhost:2375 without TLS.

This is enough to use Docker normally in the Ubuntu terminal.

Docker with WSL2 without Docker Desktop

Docker Desktop is paid for use in large companies, however, it is not necessary to run Docker.

There are multiple alternatives:

Docker in WSL2 with Systemd

In another part of this article, I explain how to enable Systemd by editing the file /etc/wsl.conf.

  1. Remove old packages

    for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
    
sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
rm ~/.docker/config.json
  1. Add the official Docker apt repository

    # Adiciona a chave GPG oficial do Docker
    sudo apt update
    sudo apt install ca-certificates curl gnupg
    sudo install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    sudo chmod a+r /etc/apt/keyrings/docker.gpg
    
    # Adiciona o repositório apt à lista
    echo \
      "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
  2. Install Docker and the docker-compose-plugin

    sudo apt update && \
    sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    

    Update: the docker-compose v1 is the old Python version, without updates since May 2021. The plugin was rewritten in Go and its command is now docker compose (with a space instead of a hyphen).

  3. Optionally, add your user to the docker group to avoid using sudo:

    sudo usermod -aG docker $USER
    

    See possible updates in the official documentation.

Be aware that this could be a security loophole.

  1. Test the installation

    sudo docker run hello-world
    

Docker with Rancher Desktop

Rancher is a good replacement for Docker Desktop, especially for Kubernetes. It can be installed via Chocolatey:

choco install rancher-desktop

NVIDIA Container Toolkit

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
  && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update && sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
$ cat /etc/docker/daemon.json
{
    "runtimes": {
        "nvidia": {
            "args": [],
            "path": "nvidia-container-runtime"
        }
    }
}
sudo systemctl restart docker

Test with the following command:

docker run --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark

Visual Studio Code with WSL2

VS Code installed on Windows has native integration with WSL2. You will need to install the extensions in WSL2 as well.

GUI for Git

Using Git through the command line is excellent for almost everything, but some tasks are easier to perform visually.

Tools installed on Windows may suffer from performance issues when accessing the WSL file system, so I recommend installing them directly on Linux. This eliminates some GUIs like Sourcetree.

The tools I have tested and liked are:

  • VS Code

    • It already comes with a good version control tool. Some extensions offer more functionalities, but I don’t use them.
  • gitk

    • It was the first GUI for Git. I use it a lot to view changes in a single file.
  • GitKraken

    • It is very comprehensive and visually appealing, but it is a paid tool.
    sudo apt update
    sudo apt install -y libgbm-dev libnotify4
    wget https://release.gitkraken.com/linux/gitkraken-amd64.deb
    sudo dpkg -i ./gitkraken-amd64.deb
    sudo apt install -f
    
  • Gittyup (fork of GitAhead)

    • Through Flatpak:

      $ flatpak search gittyup
      Name    Description          Application ID             Version Branch Remotes
      Gittyup Graphical Git client com.github.Murmele.Gittyup v1.3.0  stable flathub
      
      flatpak install flathub com.github.Murmele.Gittyup
      
flatpak run --nosocket=fallback-x11 --socket=x11 com.github.Murmele.Gittyup
  • AppImage:
wget -q -O ~/bin/gittyup \
      $(wget -q -O - https://api.github.com/repos/Murmele/Gittyup/releases | \
        jq -r '.[0].assets[] | select(.name | test("^Gittyup.*AppImage$")) | .browser_download_url') && \
    chmod +x ~/bin/gittyup && \
    gittyup --version

AWS CLI

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

or with asdf:

asdf plugin add awscli
asdf install awscli latest
asdf global awscli latest

Access via SSH

WSL2 is a virtual machine with its own IP address.

This address can be found in the following ways:

  1. Install OpenSSH
sudo apt install openssh-server
  1. Adjust settings in /etc/ssh/sshd_config
Port 2255
ListenAddress 0.0.0.0
PasswordAuthentication yes
  1. Discover the VM’s IP address

Using iproute2 in WLS2:

$ ip addr show eth0
       inet 172.21.145.176/20 brd 172.21.159.255 scope global eth0

Or, through PowerShell:

$ wsl -- ip -o -4 -j addr s eth0 | ConvertFrom-Json | %{ $_.addr_info.local } | ?{ $_ }
172.21.145.176

Note: the value in /etc/resolv.conf is the host’s address, not the VM’s.

$wsl    = wsl -- ip -o -4 -j addr s eth0 | ConvertFrom-Json | %{ $_.addr_info.local } | ?{ $_ }
$host = (Get-NetIPAddress).IPAddress | ?{ $_ -match ($wsl -replace '^((\d+\.){2}).*$','^$1') }
$wsl,$host
  1. Check if the service is running

Read the section above on how to enable Systemd first.

$ sudo systemctl status sshd.service
   ● ssh.service - OpenBSD Secure Shell server
        Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
        Active: active (running) since…
  1. Create a portproxy between the VM and the Host

In an admin PowerShell:

netsh interface portproxy add v4tov4 listenport=2255 listenaddress=0.0.0.0 connectport=2255 connectaddress=172.21.145.176
  1. Allow port 2255 in the Firewall
netsh advfirewall firewall add rule name="Open Port 2255 for WSL2" dir=in action=allow protocol=TCP localport=2255
$ netsh interface portproxy show v4tov4

   Listen on ipv4:             Connect to ipv4:

   Address         Port        Address         Port
   --------------- ----------  --------------- ----------
   0.0.0.0         2255        172.21.145.176  2255

Scanner

There are many programs to interact with the scanner, but the best one I know is XSane, which is a frontend for SANE.

sudo apt install xsane

I have a Canon Pixma MG5450 multifunction printer. The full name does not appear on the compatible devices page, but it is part of the “PIXMA MG5400 Series”, which is included in the sane-pixma backend.

The command scanimage -L broadcasts to detect connected scanners. By default, Canon devices can be discovered using the BJNP protocol on UDP port 8612.

Unfortunately, this command did not detect my scanner at first.

I knew it was not a connection error because curl http://192.168.15.7 returns the printer’s page (this IP is fixed on my DHCP server).

The solution was to explicitly state the printer’s IP in the pixma.conf file:

echo "bjnp://192.168.15.7" | sudo tee -a /etc/sane.d/pixma.conf

The command worked without issues after that:

$ scanimage -L
device `pixma:MG5400_192.168.15.7' is a CANON Canon PIXMA MG5400 Series multi-function peripheral

The --all parameter lists possible options compatible with the backend used:

$ scanimage --device "pixma:MG5400_192.168.15.7" --all
Output format is not set, using pnm as a default.

All options specific to device `pixma:MG5400_192.168.15.7':
  Scan mode:
    --resolution auto||75|150|300|600|1200|2400dpi [75]
        Sets the resolution of the scanned image.
    --mode auto|Color|Gray|Lineart [Color]
        Selects the scan mode (e.g., lineart, monochrome, or color).
    --source Flatbed [Flatbed]
        Selects the scan source (such as a document-feeder). Set source before
        mode and resolution. Resets mode and resolution to auto values.

This way, I could scan a document at 150 dpi directly from the command line using scanimage:

scanimage \
  --device "pixma:MG5400_192.168.15.7" \
  --format=png \
  --output-file scan.png \
  --resolution 150 \
  --progress

However, it’s much easier with XSane.

Audio

Programs like Virtual Audio Cable and Voicemeeter are useful for configurations with multiple speakers and for streaming. The free versions of both can be installed via Chocolatey.

  1. Go to Control Panel\Hardware and Sound » Sound;
  2. Under Playback, set VoiceMeeter Input as the default device and VoiceMeeter Aux Input as the default communication device;
  3. In Recording, set VoiceMeeter Output as the default device and VoiceMeeter Aux Output as the default communication device;
  4. Go to the Advanced tab in the properties of each device and set the sample rate (e.g., 24 bit, 48000 Hz). The sample rate should be set to the same value in Voicemeeter (in Menu » System settings » Preferred Main SampleRate).
  5. Example configuration for Voicemeeter Banana:
    • Hardware Input 1: Notebook microphone
    • Hardware Input 2: Headset microphone
    • Hardware Input 3: CABLE Output (VB-Audio Virtual Cable)
    • Voicemeeter VAIO: Desktop Output » A1, B1
    • Voicemeeter AUX: Calls Output » A1
    • A1: WDM: Speakers / Headphones
    • A2: WDM: Headset
    • A3: WDM: TV connected via HDMI
  • Note 1: I only set up my Bluetooth headset microphone when I use it, as it saves energy and I can use the headphones in high-quality sound mode.

  • Note 2: I had an issue with Spotify after installing Voicemeeter. I solved it by reinstalling Spotify.

Another very useful program is EarTrumpet. It allows you to set, for each program, which audio output to use and at what volume.

Streaming

For video calls where I want to share the sound being played on the computer in addition to my microphone, but without the sound from the call itself (other participants’ voices):

  • In Meets/Teams/Discord/Skype:
    • Microphone: VoiceMeeter Output
    • Speaker: VoiceMeeter Aux Input
  • In VoiceMeeter:
    • Mic PC: B1
    • Desktop (Voicemeeter VAIO): A1, B1
    • Calls (Voicemeeter AUX): A1

Julio Batista Silva
Julio Batista Silva
Data Engineer

I’m a computer engineer passionate about science, technology, photography, and languages. Currently working as a Data Engineer in Germany.

comments powered by Disqus