$linuxjunkies
>

A Complete Linux Developer Workstation Setup

Set up a complete Linux developer workstation: distro selection, terminal stack, language version managers, Docker, VS Code, and reproducible dotfiles.

IntermediateUbuntuDebianFedoraArch12 min readUpdated June 7, 2026

Before you start

  • A fresh or existing Linux installation with sudo access
  • Internet connectivity to download packages and language runtimes
  • A GitHub or GitLab account for remote dotfile storage

Setting up a Linux developer workstation from scratch involves more than installing a few packages. Choices made early—distro, shell, runtime managers—compound into hours saved or lost later. This guide walks through each layer systematically, from distro selection to dotfile management, so you end up with a reproducible, sane environment.

Choosing a Distro

For most developers, the practical choice comes down to three families:

  • Ubuntu 24.04 LTS / Debian 12: Widest tool compatibility, largest community, predictable release cadence. Ubuntu ships newer kernels via HWE stacks. Best default for teams that need consistency.
  • Fedora 40+: Ships upstream software fast—latest kernels, Wayland-first, Pipewire by default. SELinux enforcing out of the box. Good if you eventually target RHEL/Rocky in production.
  • Arch Linux: Rolling release; you control exactly what's installed. Requires more upfront effort but produces a lean, well-understood system. The AUR covers almost every developer tool.

All three work well. Pick Ubuntu/Debian if you want minimal friction; pick Fedora if you want bleeding-edge without full DIY; pick Arch if you want to own every layer.

Base System Updates and Essential Packages

Before anything else, fully update the system and install a common baseline.

Debian / Ubuntu

sudo apt update && sudo apt upgrade -y
sudo apt install -y \
  build-essential curl wget git gnupg ca-certificates \
  unzip zip tar xz-utils jq ripgrep fd-find bat tree htop

Fedora

sudo dnf upgrade -y
sudo dnf install -y \
  @development-tools curl wget git gnupg2 ca-certificates \
  unzip zip tar xz jq ripgrep fd-find bat tree htop

Arch

sudo pacman -Syu
sudo pacman -S --needed \
  base-devel curl wget git gnupg unzip zip tar xz \
  jq ripgrep fd bat tree htop

Note: On Ubuntu, fd-find installs as fdfind; symlink it with ln -s $(which fdfind) ~/.local/bin/fd.

Terminal Stack

Shell: Zsh with a Plugin Manager

Bash is fine; Zsh with good plugins is noticeably faster to work in. Install Zsh and set it as your default shell, then add Sheldon (a fast, TOML-configured plugin manager) or the simpler Oh My Zsh if you prefer convention over configuration.

# Install Zsh (all distros have it)
sudo apt install -y zsh        # Debian/Ubuntu
sudo dnf install -y zsh        # Fedora
sudo pacman -S zsh             # Arch

chsh -s $(which zsh)
# Install Sheldon plugin manager
curl --proto '=https' --tlsv1.2 -LsSf \
  https://github.com/rossmacarthur/sheldon/releases/latest/download/sheldon-installer.sh \
  | sh

Essential plugins to declare in ~/.sheldon/plugins.toml: zsh-autosuggestions, zsh-syntax-highlighting, and zsh-completions. Log out and back in for the shell change to take effect.

Terminal Emulator

On Wayland, Ghostty or Alacritty are GPU-accelerated and work natively without XWayland. WezTerm is a strong cross-platform choice with built-in multiplexing. Avoid outdated terminals like xterm for daily driving.

# WezTerm on Debian/Ubuntu
curl -fsSL https://apt.fury.io/wez/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/wezterm.gpg
echo "deb [signed-by=/usr/share/keyrings/wezterm.gpg] https://apt.fury.io/wez/ * *" \
  | sudo tee /etc/apt/sources.list.d/wezterm.list
sudo apt update && sudo apt install -y wezterm
# Alacritty on Fedora
sudo dnf install -y alacritty

# Alacritty on Arch
sudo pacman -S alacritty

Multiplexer: tmux or Zellij

tmux is ubiquitous and scriptable. Zellij ships with a discoverable UI and WebAssembly plugin support—good if you find tmux key bindings opaque.

sudo apt install -y tmux     # Debian/Ubuntu
sudo dnf install -y tmux     # Fedora
sudo pacman -S tmux          # Arch

Language Runtime Managers

Never install language runtimes solely through your distro's package manager for development use—you'll need multiple versions. Use dedicated version managers instead.

Node.js — fnm

fnm (Fast Node Manager) is written in Rust, installs in milliseconds, and is compatible with .nvmrc files.

curl -fsSL https://fnm.vercel.app/install | bash
# Add to ~/.zshrc or ~/.bashrc:
eval "$(fnm env --use-on-cd)"

# Install and use a Node version
fnm install --lts
fnm use lts-latest

Python — pyenv

curl https://pyenv.run | bash
# Add to shell profile:
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

pyenv install 3.12.4
pyenv global 3.12.4

Rust — rustup

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

Go

Download the official tarball rather than using distro packages—distros lag behind upstream significantly.

# Replace 1.22.5 with the current release from go.dev/dl
wget https://go.dev/dl/go1.22.5.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrc

Docker and Containers

Install Docker Engine directly from Docker's own repository—not the distro-packaged docker.io, which is often outdated.

Debian / Ubuntu

curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Fedora

sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Post-install: run Docker without sudo

sudo systemctl enable --now docker
sudo usermod -aG docker $USER
# Log out and back in, then verify:
docker run --rm hello-world

For rootless Docker (strongly recommended on shared machines), see the official rootless setup guide.

VS Code and IDEs

VS Code

# Debian/Ubuntu
wget -qO- https://packages.microsoft.com/keys/microsoft.asc \
  | gpg --dearmor | sudo tee /usr/share/keyrings/microsoft.gpg > /dev/null
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] \
  https://packages.microsoft.com/repos/code stable main" \
  | sudo tee /etc/apt/sources.list.d/vscode.list
sudo apt update && sudo apt install -y code
# Fedora
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo sh -c 'echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo'
sudo dnf install -y code
# Arch (AUR)
yay -S visual-studio-code-bin

Wayland note: Launch VS Code with native Wayland rendering to avoid blurry fonts under XWayland: add --ozone-platform=wayland --enable-features=WaylandWindowDecorations to your .desktop launcher or shell alias.

JetBrains IDEs

Use JetBrains Toolbox to install and update any JetBrains IDE. Download the tarball from jetbrains.com/toolbox-app, extract it, and run the binary—it handles everything else including systemd integration for auto-updates.

Neovim

If you prefer a terminal editor, install Neovim 0.10+ and bootstrap with LazyVim or kickstart.nvim rather than configuring from scratch.

sudo apt install -y neovim          # Ubuntu 24.04 ships 0.9+; use PPA for 0.10
sudo dnf install -y neovim         # Fedora ships current
sudo pacman -S neovim              # Arch always current

Dotfile Management

Dotfiles are the single highest-leverage investment in a developer workstation. A good system lets you reproduce your environment on any machine in minutes.

The bare Git repository approach requires no extra tooling:

# Initialize once
git init --bare $HOME/.dotfiles
alias dotfiles='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
dotfiles config --local status.showUntrackedFiles no

# Track files
dotfiles add ~/.zshrc ~/.gitconfig ~/.config/wezterm/wezterm.lua
dotfiles commit -m "Initial dotfiles"
dotfiles remote add origin [email protected]:youruser/dotfiles.git
dotfiles push -u origin main
# Bootstrap on a new machine
git clone --bare [email protected]:youruser/dotfiles.git $HOME/.dotfiles
alias dotfiles='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
dotfiles checkout
dotfiles config --local status.showUntrackedFiles no

Alternatively, chezmoi adds templating (useful when config differs between machines) and encrypts secrets. Install it with sh -c "$(curl -fsLS get.chezmoi.io)".

Verification

Run these checks to confirm the core stack is healthy:

echo $SHELL                  # should be /usr/bin/zsh or /bin/zsh
node --version               # e.g., v20.15.0
python3 --version            # e.g., Python 3.12.4
rustc --version              # e.g., rustc 1.79.0
go version                   # e.g., go1.22.5 linux/amd64
docker info | grep -i server # should return server details, not permission errors
code --version               # VS Code version string

Troubleshooting

  • Docker permission denied: You haven't logged out since adding yourself to the docker group. Run newgrp docker in the current session as a temporary fix, then log out properly.
  • pyenv: python version not found: Install build dependencies first. On Debian/Ubuntu: sudo apt install -y libssl-dev libbz2-dev libreadline-dev libsqlite3-dev libffi-dev zlib1g-dev.
  • VS Code blurry on Wayland: Add the Wayland flags described above; also check that WAYLAND_DISPLAY is set in your environment (echo $WAYLAND_DISPLAY).
  • fnm / pyenv not found after install: The installers append to ~/.bashrc. If you switched to Zsh, manually add the init lines to ~/.zshrc and reload with source ~/.zshrc.
  • Slow Zsh startup: Profile with zsh -i -c exit timing or zprof. Common culprits are NVM (replace with fnm), heavy Oh My Zsh plugins, or pyenv init in the wrong place.
tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

Should I use the distro-packaged Docker or install from Docker's repository?
Install from Docker's own repository. Distro packages (like Ubuntu's docker.io) lag months behind upstream and may lack features like the compose plugin. The official repo ensures you get current releases.
Why use fnm or pyenv instead of just apt/dnf for language runtimes?
Distro packages give you one version system-wide and often trail upstream by 6-18 months. Version managers let you switch between Node 18 and 22, or Python 3.10 and 3.12, per project without conflicts.
Is a bare Git repository approach for dotfiles safe to use on multiple machines with different configs?
It works well for identical configs. If your machines differ (different hostnames, OS-specific paths), chezmoi's templating system handles per-machine variation and also encrypts secrets—it's worth the extra learning curve.
Does VS Code run natively on Wayland or does it use XWayland?
By default VS Code uses XWayland, which can cause blurry rendering on HiDPI displays. Pass --ozone-platform=wayland to the binary or add it to your .desktop file's Exec line to get native Wayland rendering.
What is the minimum a developer should track in dotfiles?
At minimum: ~/.zshrc or ~/.bashrc, ~/.gitconfig, and your editor config (e.g., ~/.config/nvim or VS Code's settings.json). Add terminal emulator configs and tmux.conf next. SSH config and keys should be handled separately with proper secret management.

Related guides