September 8, 2026 · 2 min read

.Net Linux Workstation

On this page

Describes one way to setup a professional Linux based .Net developer workstation

.Net Linux Workstation

OS Installation

Configuring Workstation Identity

You want to set your workstation hostname so it's easy to identify on the network

Terminal
sudo hostnamectl set-hostname <your-new-name>

Optimizing OS & Application Updates

apt is a great software package manager but on a fresh install I like to install and use nala. It is not a replacement for apt but it's a different front-end for it that adds the following features:

  1. Parallel Downloads
  2. Fastest Mirror Helper
  3. Transaction History with Undo
  4. More readable output

Install Nala

Terminal
sudo apt install nala

Find the 5 fastest mirrors

You can use nala to find the fastest mirrors for your country. Below I'm searching the US for the 5 fasted mirrors

Terminal
sudo nala fetch --ubuntu noble --country US --https-only --auto --fetches 5

Configuring the Terminal

Modern terminals demand a nerd font with ligatures to look there best. A nice font is Google Sans Code NF font.

Install dependencies

Terminal
sudo nala install -y curl unzip fontconfig

Download & Install

Terminal
mkdir -p ~/.local/share/fonts/google-sans-code-nfm
cd /tmp
curl -fL -o GoogleSansCode.tar.xz \
  https://github.com/ryanoasis/nerd-fonts/releases/download/v3.5.1/GoogleSansCode.tar.xz
mkdir -p google-sans-code-nfm
tar -xf GoogleSansCode.tar.xz -C google-sans-code-nfm
find google-sans-code-nfm -type f -iname '*NerdFontMono*.ttf' \
  -exec cp -v {} ~/.local/share/fonts/google-sans-code-nfm/ \;

Refresh Font Cache

Terminal
fc-cache -fv ~/.local/share/fonts/google-sans-code-nfm

Application Installation

1Password

Just about every application you'll install will need some form of authentication so it's a good idea to install your password manager & it's browser plug-in first

Terminal
wget -P ~/Downloads "https://downloads.1password.com/linux/debian/amd64/stable/1password-latest.deb" &&
sudo apt install ~/Downloads/1password-latest.deb

Brave Origin

Brave Origin is the Brave browser with all of the non-browser applications stripped out.

Terminal
curl -fsS https://dl.brave.com/install.sh | FLAVOR=origin sh

Once you've installed Brave Origin open it and set it as your default browser.

1Password for Brave Extension

Next install the 1Password extension for Brave so that you can auto-login to various web apps.

1Password Extension

Grok Build

Installing an AI agent is a great first step as it can help you along the way with troubleshooting and optimizing the remainder of the setup if you need help.

Terminal
curl -fsSL https://x.ai/cli/install.sh | bash

Git and gitconfig

git is already installed on modern linux based systems but there are some config values worth setting. You can create a ~/.gitconfig file to set your global git settings. Below is a sample setup.

config
1[user]2	name = <your name>3	email = <your email>4[init]5	defaultBranch = master6[core]7	editor = nano8	autocrlf = input9[column]10	ui = auto11[branch]12	sort = -committerdate13[commit]14	verbose = true15[tag]16	sort = version:refname17[pull]18	ff = only19[rebase]20	autoStash = true21	updateRefs = true22	autoSquash = true23[fetch]24	prune = true25[push]26	autoSetupRemote = true27[rerere]28	enabled = true29[merge]30	conflictstyle = zdiff331[diff]32	algorithm = histogram33	colorMoved = zebra34[alias]35	st = status -sb36	br = branch -vv37	sw = switch38	co = checkout39	ci = commit40	last = log -1 HEAD --stat41	lg = log --graph --decorate --oneline --all42	please = push --force-with-lease --force-if-includes

SSH

Setting up ssh is a matter of putting your private key files in your ~/.ssh folder and then setting up your ~/.ssh/config` file to reference those private keys when working with the various git remotes.

Once the private keys and config file are in place you can set permissions by running:

Terminal
chmod 700 ~/.ssh && chmod 600 ~/.ssh/*

Obsidian

I use Obsidian to organize all of my personal notes. Adjust the below url based on the version that is current at the time.

Obsidian Download Page

Terminal
cd ~/Downloads
wget https://github.com/obsidianmd/obsidian-releases/releases/download/v1.13.7/obsidian_1.13.7_amd64.deb &&
sudo nala install ./obsidian_1.13.7_amd64.deb

Sublime Merge

Along with git, we need a great git client and Sublime Merge is excellent.

Terminal
# 1. Trust Sublime's signing key
wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/sublimehq-archive.gpg > /dev/null

# 2. HTTPS transport (usually already present on Pop!_OS; harmless if it is)
sudo nala install apt-transport-https

# 3. Add the stable repo (same list is used for Sublime Text and Merge)
echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list

# 4. Refresh and install
sudo nala update
sudo nala install sublime-merge

.Net SDK

Install the sdk with the installer script

Terminal
# Download the dotnet-install script
cd ~/Downloads
curl -L https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh

# Make the dotnet-install script executable
chmod +x ./dotnet-install.sh

# Install the latest version (which might not be the LTS version)
./dotnet-install.sh --version latest

Update your $HOME/.bashrc

Place the following in your .bashrc file

Terminal
# set dotnet env vars
export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools

Finally reload your .bashrc

Terminal
source $HOME/.bashrc

Verify .Net SDK Installation

Terminal
dotnet --list-sdks

Docker Engine

We need Docker Engine and Docker Compose to run our .Net Testcontainers and other image based services like Postgres and Mailhog

Terminal
sudo nala install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo nala update
sudo nala install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 

sudo usermod -aG docker $USER

After installation you need to log out and back in and then verify with docker run --rm hello-world

Jetbrains Rider

Terminal
cd ~/Downloads
curl -L "https://data.services.jetbrains.com/products/download?code=RD&platform=linux" -o rider.tar.gz
sudo tar -xzf rider.tar.gz -C /opt

/opt/JetBrains\ Rider-*/bin/rider.sh

Within the Jetbrains Rider IDE: Configure -> Create Desktop Entry

Jetbrains DataGrip

Terminal
cd ~/Downloads
curl -L "https://data.services.jetbrains.com/products/download?code=DG&platform=linux" -o datagrip.tar.gz
sudo tar -xzf datagrip.tar.gz -C /opt

/opt/DataGrip-*/bin/datagrip.sh

Within the DataGrip IDE: Configure -> Create Desktop Entry

NodeJS

For node we use a node version manager and we also update not only our ~/.bashrc so that we can leverage node from our terminals but also we modify ~/.profile so that applications like JetBrains Rider IDE can also access and use node

Terminal
set -euo pipefail

sudo nala install curl git build-essential

export NVM_DIR="$HOME/.nvm"
NVM_VERSION=v0.40.5

if [ ! -s "$NVM_DIR/nvm.sh" ]; then
  curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" | bash
fi

set +u
# shellcheck disable=SC1091
. "$NVM_DIR/nvm.sh"
set -u

nvm install --lts
nvm alias default 'lts/*'

PROFILE="$HOME/.profile"
touch "$PROFILE"

START='# >>> nvm-gui >>>'
END='# <<< nvm-gui <<<'

SNIPPET=$(cat <<'EOF'
# >>> nvm-gui >>>
# POSIX-safe PATH for GUI apps (Rider). Do not source nvm.sh here (it needs bash).
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
if [ -s "$NVM_DIR/alias/default" ]; then
  nvm_default=$(cat "$NVM_DIR/alias/default")
  while [ -s "$NVM_DIR/alias/$nvm_default" ]; do
    nvm_default=$(cat "$NVM_DIR/alias/$nvm_default")
  done
  nvm_bin="$NVM_DIR/versions/node/$nvm_default/bin"
  if [ -d "$nvm_bin" ]; then
    case ":$PATH:" in
      *":$nvm_bin:"*) ;;
      *) PATH="$nvm_bin:$PATH" ;;
    esac
  fi
  unset nvm_default nvm_bin
fi
# <<< nvm-gui <<<
EOF
)

if grep -qF "$START" "$PROFILE"; then
  tmp=$(mktemp)
  awk -v start="$START" -v end="$END" '
    $0 == start { skip=1; next }
    $0 == end { skip=0; next }
    !skip { print }
  ' "$PROFILE" > "$tmp"
  mv "$tmp" "$PROFILE"
fi

printf '\n%s\n' "$SNIPPET" >> "$PROFILE"

echo
echo "node: $(command -v node)  $(node -v)"
echo "npm:  $(command -v npm)   $(npm -v)"
echo
echo "Log out of COSMIC and back in (or reboot) so Rider inherits the new PATH."
echo "Then in Rider: File → Invalidate Caches is not needed; just restart Rider."

Spotify

Terminal
curl -sS https://download.spotify.com/debian/pubkey_5384CE82BA52C83A.asc | sudo gpg --dearmor --yes -o /etc/apt/trusted.gpg.d/spotify.gpg
echo "deb https://repository.spotify.com stable non-free" | sudo tee /etc/apt/sources.list.d/spotify.list

sudo nala update && sudo nala install spotify-client

Wezterm

Terminal
curl -fsSL https://apt.fury.io/wez/gpg.key | sudo gpg --yes --dearmor -o /usr/share/keyrings/wezterm-fury.gpg
echo 'deb [signed-by=/usr/share/keyrings/wezterm-fury.gpg] https://apt.fury.io/wez/ * *' | sudo tee /etc/apt/sources.list.d/wezterm.list
sudo chmod 644 /usr/share/keyrings/wezterm-fury.gpg

sudo nala update &&
sudo nala install wezterm-nightly

Keep reading