/dotfiles-wsl

wsl2 + Ubuntu

Primary LanguageShellMIT LicenseMIT

WSL2 Ubuntu environment

GitHub license GitHub stars GitHub commits

AboutWindows 11ChocolateyUbuntuTodo

About

This repository contains my personal dotfiles used to set up a new development environment on Windows using WSL2 with Ubuntu. The focus of the setup is on two main tools: Visual Studio Code and IntelliJ IDEA, which are my preferred development environments for programming tasks. Additionally, for other tasks, I use Windows Terminal.

Windows 11

To set up Windows 11 after fresh install in automatic mode, let's download the Sophia Script.

Download and expand the latest Powershell module of the script:

irm script.sophi.app -useb | iex

Command below are meant to be executed in Administrator mode.

Set execution policy, get into the module directory, download our custom script preset and launch it:

# Set-ExecutionPolicy Bypass -Scope Process -Force; Set-Location -Path ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path + '\Sophi*'); (New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/aubique/871ad87ef7a801d17942ca3974cd9909/raw/0deebdbb7a015399b2408cd790357ab4afce6248/Sophie.ps1') | Out-File .\Sophie.ps1; .\Sophie.ps1

Script will set up environment, customize appearance, remove telemetry and UWPApp bloatware. For WSL2 it installs Virtual Machine Platform, WSL Kernel and GUI App Support (WSLg). After you've completed running script functions, restart the PC and proceed with Linux distribution installation:

wsl --install -d Ubuntu
Install WSL2 manually

Enable WSL and VirtualMachinePlatform features in Powershell console:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

Reboot your PC. Download and install the Linux kernel update package:

Install the update via Powershell:

$wslUpdateInstallerUrl = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi"
$downloadFolderPath = (New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path
$wslUpdateInstallerFilePath = "$downloadFolderPath/wsl_update_x64.msi"
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($wslUpdateInstallerUrl, $wslUpdateInstallerFilePath)
Start-Process -Filepath "$wslUpdateInstallerFilePath"

Set WSL default version to 2

wsl --set-default-version 2

Dotfiles

As soon as Ubuntu distribution is installed you can download the dotfiles. To avoid conflict with the existing files you can clone it the temporary folder. Then copy with rsync your dotfiles to $HOME directory.

git clone --separate-git-dir=$HOME/.dotfiles https://github.com/aubique/dotfiles-wsl.git tempfiles
rsync -vah --exclude '.git' tempfiles/ $HOME/
sudo rsync -vah $HOME/pub/etc/ /etc/

Once we're done with synchronizing our config files, we delete temporary folder, update configs, sub-modules and aliases.

for s in source "/etc/profile" "$HOME/.profile"; do source $s; done
dotfiles config status.showUntrackedFiles no
rm -r tempfiles

Get back to $HOME and synchronize the sub-modules:

cd && dotfiles submodule update --init
Install Vim plugins

This repo contains a Vundle sub-module repository. That's an extension manager that helps to manage environment with plugins properly.

In case you didn't get managed to download Vundle plugin during the set above, clone it directly from GitHub:

git clone https://github.com/VundleVim/Vundle.vim.git ~/.local/share/vim/bundle/Vundle.vim

Afterwards, you have to open Vim and run :PluginInstall that downloads automatically the plugins listed in your $VIMDOTDIR/vimrc.

If you've got Warning: Cannot find word list error message, create spell folder and download the files:

mkdir -pv ~/.config/vim/spell
vim 1.md +'set spell'

User Shell Folders

There is no point to keep all the user files on drive C:\ or the same partition that has the Windows directory. You can't move all user files but you can certainly relocate Documents, Pictures, Videos, Downloads, Music to a different partition (drive).

While you allocate a distinct partition with diskmgmt.msc, you may find more intuitive to adopt Linux Filesystem Hierarchy Standard (FHS) on it. Then synchronize the Windows user shell folders with WSL home user folders.

You can change user folder programmatically executing the script with interactive prompt:

bash $RUNSCRIPTS_PATH/relocate_user_shell_folders.sh

The bash script is provided with ps1 scripts, so make sure that Powershell is initialized properly.

The script automates such tasks:

  1. Move User Shell folder location to another drive or directory
  2. Link the $HOME user folders for WSL to the existing Windows user shell folders
  3. Update Windows system PATH environment variable with the links on new partition

Chocolatey

Chocolatey is software management automation for Windows that wraps installers, executables, zips and scripts into compiled packages.

Install Chocolatey CLI

First, ensure that you are using an administrative shell.

To install Chocolatey with powershell.exe paste the copied text into your shell and press Enter:

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'))

Now you can manage Windows applications and packages using Chocolatey in administrative shell, check out a list of installed packages with choco list --local.

Install a pack of applications listed in pkglist_choco.txt:

Get-Content \\wsl$\Ubuntu\home\*\pub\pkglist_choco.txt | Select-String -NotMatch '^#.*' | ForEach {iex "choco install -y $_"}

Context Menu & Fixes

After having installed Chocolatey and packages, you may want to clean up the context menu.

Remove VLC from context menu.
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
Remove-Item HKCR:\Directory\shell\AddToPlaylistVLC\ -Recurse
Remove-Item HKCR:\Directory\shell\PlayWithVLC\ -Recurse
Hide 7-Zip cascaded context menu.

With regedit.exe you can find HKEY_CLASSES_ROOT\CLSID{23170F69-40C1-278A-1000-000100020000} that's linked to the 7-Zip DLL file. All 7-Zip context menu options are defined in this DLL file, they're invoked every time Windows needs to show the menu and thus not static.

You can disable these options with 7-Zip GUI (as Admin) via menu Tools -- Options -- 7-Zip -- Integrate 7-Zip to shell context menu

Bypass Windows requirements check in Ventoy

Ventoy is a good solution for installing Windows 11 on incompatible devices. That said we have to explicitly set in JSON config the parameter VTOY_WIN11_BYPASS_CHECK, that creates certain Registry keys to bypass RAM, TMP, Secure Boot, CPU and Storage checks on the machine.

Run this in WSL2 to add the configuration JSON file to the ventoy subfolder installed with Chocolatey:

powershell.exe "choco list -lo" | grep ventoy && \
cp -fT ~/pub/etc/ventoy.json "$(readlink -e /mnt/c/Users/*/AppData/Local/ventoy/ventoy)/ventoy.json"
Personalize Start menu

Turn Off Show recently opened items in Start, Jump Lists, and File Explorer" for Current User:

Set-ItemProperty -path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -name "Start_TrackDocs" -value "0"

Disable Recently added Apps List on the Start Menu for the User:

Set-ItemProperty -path "HKCU:\Software\Policies\Microsoft\Windows\Explorer" -name "HideRecentlyAddedApps" -value "1"

Otherwise, you set it up in Settings -> Personalization -> Start

For Windows 10 you can use another Powershell debloater from GitHub.

Windows Terminal

In order to open the administrative shell in Windows Terminal you may want to use Gsudo, sudo equivalent for Windows. It allows to run commands with elevated permissions, or to elevate the current shell, in the current console window or a new one.

In case you it's not installed with other packages, you can run choco install gsudo

Now you can elevate permissions powershell.exe gsudo powershell.exe -nologo. If you set it up in settings.json you can launch it on Windows Terminal. To do that, you can paste the content of profiles.

  • Windows 11: $env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
  • WSL 2: /mnt/c/Users/*/AppData/Local/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json
settings.json
  "defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
  "launchMode": "maximized",
  "profiles": {
    "defaults": {
      "closeOnExit": "graceful",
      "cursorColor": "#FFFFFF",
      "cursorShape": "filledBox",
      "font": {
        "face": "Cascadia Code",
        "size": 12
      },
      "hidden": false,
      "snapOnInput": true
    },
    "list": [
      {
        "colorScheme": "Campbell Powershell",
        "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
        "name": "PowerShell",
        "startingDirectory": null
      },
      {
        "colorScheme": "Ubuntu-ColorScheme",
        "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}",
        "name": "Ubuntu WSL \u25a4",
        "source": "CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc"
      },
      {
        "commandline": "wsl genie -c ~/.config/scripts/genie-tmux.sh",
        "font": {
          "face": "Lucida Console"
        },
        "guid": "{2862b68e-b019-4846-bbdd-5f10c363cb1a}",
        "icon": "https://assets.ubuntu.com/v1/49a1a858-favicon-32x32.png",
        "name": "Ubuntu WSL \ud83d\udccc",
        "suppressApplicationTitle": true,
        "useAcrylic": true
      },
      {
        "commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
        "guid": "{a266a539-53e6-4b70-abf9-dfd2f76a2b97}",
        "hidden": true,
        "icon": "ms-appx:///Images/Square44x44Logo.targetsize-32.png",
        "name": "PowerShell \u26a1",
        "padding": "0, 0, 0, 0",
        "suppressApplicationTitle": true
      }
    ]
  },
  "schemes": [
    {
      "background": "#0C0C0C",
      "black": "#0C0C0C",
      "blue": "#0037DA",
      "brightBlack": "#767676",
      "brightBlue": "#3B78FF",
      "brightCyan": "#61D6D6",
      "brightGreen": "#16C60C",
      "brightPurple": "#B4009E",
      "brightRed": "#E74856",
      "brightWhite": "#F2F2F2",
      "brightYellow": "#F9F1A5",
      "cursorColor": "#FFFFFF",
      "cyan": "#3A96DD",
      "foreground": "#CCCCCC",
      "green": "#13A10E",
      "name": "Campbell",
      "purple": "#881798",
      "red": "#C50F1F",
      "selectionBackground": "#FFFFFF",
      "white": "#CCCCCC",
      "yellow": "#C19C00"
    },

The WSL environment we're about to setup has an environment variable - ${WIN_TERM} that stores in .bashrc a path to the Windows Terminal settings.json. Follow the steps above to get Ubuntu and dotfiles installed.

WSL2 startup genie-tmux.sh script uses Genie systemd and Tmux multiplexer, mostly described in the Genie installation step.

Check out docs.microsoft.com to figure out the profile settings in Windows Terminal.

Windows Firewall

You can set a rule in wf.msc by subnet and interface dedicated to WSL2:

New-NetFirewallRule -DisplayName "from WSL2" -Direction Inbound -Action Allow -LocalAddress "172.16.0.0/12" -InterfaceAlias "vEthernet (WSL)"

You can also allow SSH connections on 32022 and open other ports to access VMWare virtual machines.

New-NetFirewallRule -DisplayName "SSH/RDP > WSL2" -Direction Inbound -Action Allow -Protocol TCP -LocalAddress 192.168.1.0/24,172.16.0.0/12 -LocalPort 32022,3389
New-NetFirewallRule -DisplayName "SSH/HTTP(S) > VMWare" -Direction Inbound -Action Allow -Protocol TCP -LocalAddress 192.168.1.0/24,172.16.0.0/12,172.28.144.0/24 -LocalPort 32020,32021,32023-32025,32080,32443,64190

To set up SSH Server on WSL2, check out the step describing it below.

IDE

To synchronize IDE settings between different machines you can use 2 ways:

  1. Settings Sync built-in feature or plugin
  2. Git repository for settings

VS Code

You can use the built-in feature called Settings Sync that allows you to synchronize your Visual Studio Code settings across different devices using your GitHub or Microsoft account.

More info in VSCode Docs

IntelliJ IDEA

If you have JetBrains Account with license activated, the no-brainer would be to link the settings to your account and use IDE Settings Sync plugin, since no additional configuration is required.

Check out JetBrains Docs for more info about sharing IDE settings.

Ubuntu

Install Ubuntu packages and proceed with setup of the WSL2 environment.

Common dependencies

Now we can install common dependencies and packages to setup our environment:

sudo apt update && grep -vE '^#' ~/pub/pkglist_apt.txt | xargs sudo apt install -y

SSH Server

To run sshd on WSL2 machine, you should generate and upload the SSH key to your WSL2 environment. It's well described in the "How To Generate and Upload SSH keys" gist.

For the first connection you can enable SSH password authentication via port 32022:

sudo ssh-keygen -A
sudo sed -E -e 's/^[# ]*(Port )[0-9]+$/\132022/g' -e 's/^[# ]*(PasswordAuthentication )no/\1yes/g' -i /etc/ssh/sshd_config

Execute the alias sshd_up to run SSH server.

Git

Configure Git:

git config --global push.default current
git config --global core.pager /usr/bin/less

Set username and email:

git config --global user.email "{{EMAIL}}"
git config --global user.name "{{USERNAME}}"

SSH Key

In order to manage your git repositories via SSH you should generate a new key on your new machine.

Generate a new SSH key:

ssh-keygen -t rsa -b 4096 -C "$(lsb_release -cs):$(date -I)" -f ~/.ssh/id_rsa_serv-user

Once generated you can force the key files to be kept permanently in your ~/.ssh/config file. To set the key specific to one host, you can do the following in config:

Host gitlab
	User git
	HostName gitlab.com
	PreferredAuthentications publickey
	IdentityFile ~/.ssh/id_rsa_gl-user

GitHub / GitLab

Copy the public key to the clipboard:

xclip -sel c < ~/.ssh/id_rsa_gl-user.pub

Add the generated pubic SSH keys to your profile:

GPG keys

If you have GPG secret keys for signing commits or password manager, restore them.

On old system, create a backup of a GPG key:

gpg --list-secret-keys
gpg --export-secret-keys {{KEY_ID}} > /tmp/private.key

On new system, import the key:

gpg --import /tmp/private.key

Delete the /tmp/private.key on both side and install password manager you prefer.

You can check permissions for gnupg with gpg --card-status

If you have "Permission Denied" problem then you can type:

mkdir -pv ~/.config/gnupg
find $GNUPGHOME -type d -exec sudo chown $USER:$USER {} \; -exec chmod 700 {} \;
find $GNUPGHOME -type f -exec sudo chown $USER:$USER {} \; -exec chmod 600 {} \;

Systemd

Allow starting services like Docker with a systemd "bottle", arkane-systems/genie.

Set up Microsoft repository (Genie depends on .NET)

curl -sL -o /tmp/packages-microsoft-prod.deb "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
sudo dpkg -i /tmp/packages-microsoft-prod.deb
rm -f /tmp/packages-microsoft-prod.deb

Set up Arkane-Systems GPG key:

sudo curl -sL -o /usr/share/keyrings/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg

Add its repository to the sources.list:

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/wsl-transdebian.gpg] \
  https://arkane-systems.github.io/wsl-transdebian/apt/  $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/wsl-transdebian.list > /dev/null

Install Genie:

sudo apt update && sudo apt install -y systemd-genie

Copy the custom config to the system one:

sudo cp -f ~/pub/etc/genie.ini /etc/genie.ini
Disable unwanted systemd services

Services without # are supposed to be disabled, the ones with # are for complete masking:

grep -vE '^#' ~/pub/systemd_disabled.txt | xargs sudo systemctl disable
sed -En 's/#([a-z0-9\.-])/\1/p' pub/systemd_disabled.txt | xargs sudo systemctl mask

Docker

First, download a repository key into individual file in a directory dedicated for them.

On Ubuntu the standard convention is /usr/share/keyrings but any directory works (aside from /etc/apt/trusted.gpg which is the system keystore)

For the key provided in ascii-armor, like Docker's is, you'll need to dearmor the key to create a binary version, e.g.:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Then update your source file to refer to the Docker's key. E.g., in /etc/apt/sources.list.d/ have a file named docker.list with the contents:

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

This ensure that only files downloaded from official Docker repository can be signed by the that gpg key. Having the key in the system keystore allows any package in any repository to be signed by the docker key. Should that key ever compromised, it could be used to sign anything, coming from anywhere, like a hacked version of your kernel.

Optional step. For further security, create a preferences file.

E.g. in /etc/apt/preferences.d/ have a file named docker with the command:

sudo tee /etc/apt/preferences.d/docker <<EOF
Package: *
Pin: origin "download.docker.com"
Pin-Priority: 100
EOF

Setting the Pin-Priority to a value less than other repositories, which are 500 by default, prevents packages in the Docker repository from overriding packages with the same name from default repositories. This way you don't get the standard system package (e.g. new version of openssl) from Docker repository unless you specifically request it.

Update the apt package index, install the latest version of Docker Engine and containerd and add user to docker group:

sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER

Now you can start Docker daemon via Systemd.

Docker compose

sudo curl -sL -o /usr/local/bin/docker-compose \
  $(curl -s https://api.github.com/repos/docker/compose/releases/latest \
  | grep -i "browser_download_url.*$(uname -s)-$(uname -m)" | grep -v sha \
  | cut -d: -f2,3 | tr -d \")

Make docker-compose executable:

sudo chmod +x /usr/local/bin/docker-compose

Volta

Volta is a fast and reliable JavaScript tool manager.

Install Volta while skipping volta setup:

mkdir -p $VOLTA_HOME
curl https://get.volta.sh | bash -s -- --skip-setup

Install package managers and ng-cli:

volta install node npm @angular/cli

SDKman

SDKman is a tool for managing parallel versions of multiple Software Development Kits for the JVM such as Java, Gradle, Maven, Spring Boot and others.

Install SDKman without modifying shell config:

curl -sSL "https://get.sdkman.io?rcupdate=false" | bash

To initialize SDKMAN module scripts open a new terminal. Otherwise, run the following in the existing one:

source $SDKMAN_DIR/bin/sdkman-init.sh

Install AdoptOpenJDK 11:

sdk install java 11.0.11.hs-adpt

TODO

  • Upgrade the Windows Tweaks part with refined integration scripts for Windows 11
  • Migration from IntelliJ IDEA to VSCode
  • Decouple relocate_user_shell_folders.sh from gist dependencies whose links are regularly updated

Resources

Examples

Useful links and docs