Linux setup¶
A setup guide for programmers, etc., on Linux and the Windows Linux Subsystem. Alternatives for Ubuntu/Debian-like and Fedora/RedHat-like are shown.
See also
Install¶
Follow the instructions that show up to install. In Ubuntu, select “Default installation” and check “Install third-party software for graphics and Wi-Fi hardware” and “Download and install support for additional media formats”.
If you need encryption, TPM-backed FDE is a potential option. Support in Ubuntu and Fedora is experimental (as of October 2023). I have not tested it.
UEFI troubleshooting
If you get an error installing GRUB, try these steps:
- Disable Fast Boot.
- Disable Secure Boot. Also, check to see if CSM/Legacy options is disabled.
- Manually install the bootloader (not recommended).
- Read about Linux and UEFI for more troubleshooting.
Choose a partition scheme¶
Use Btrfs.¶
Btrfs is a copy-on-write option and is now much more robust than ext4. See the btrfs documentation.
Use a swap partition the same size as your RAM.¶
There’s an adage that it’s important for emergency memory – in case your main memory runs out. Meanwhile, mavericks insist on skipping it altogether, pointing out that using it for emergency memory would render a system excessively slow. Linux uses swap space as a complement to memory by swapping out infrequently used pages. You should definitely use it, but it probably doesn’t need to fit more than your memory.
For single-user systems, skip /home
in favor of /files
.¶
/home
will probably fill with miscellaneous configuration and even temp data that doesn’t need to be backed up. It’s probably even best to discard such files when upgrading or installing a new distro. So, leave /home
in the root partition and use another mount point like /data
or /files
instead.
Skip the /boot
partition.¶
It’s not needed on a modern UEFI system.
For workstations, consider separate /tmp
and /var/tmp
.¶
Things like an inefficient SQL query can quickly take hundreds of gigabytes in /tmp
. If /tmp
is in your root partition, this can brick your system, and you might have to boot to a flash drive to clean up the system. If /tmp
is a separate partition, filling it up won’t leave your system unbootable. Of course, consider the tradeoff. The same goes for /var/tmp
(more or less). If mounted as separate partitions, mount with noexec
.
Example scheme 1 – single-user workstation
drive(s) | mount point | size (GB) | filesystem | purpose |
---|---|---|---|---|
nvme0 | (efi) | 1 | FAT32 | |
nvme0 | (swap) | 64 | swap | |
nvme0 | / | 256 | btrfs | |
nvme0 | /tmp | 128 | btrfs | |
nvme0 | /var/tmp | 256 | btrfs | |
nvme0 | /data | 1308 | btrfs | Working data |
nvme1 | /docs | 1024 | btrfs | Documents |
sda | /bak | 4096 | btrfs | External backup (HDD) |
Example scheme 2 – multi-user server
Context: nvme0 and nvme1 are ultra-fast drives (CPU chipset and 4 PCIe lanes, respectively), while nvme2 and nvme3 are slower. sda
and sdb
are SATA SSDs, and sdc
is a spinning disk.
drive(s) | mount point | size (GB) | filesystem | purpose |
---|---|---|---|---|
nvme0 | (efi) | 1 | FAT32 | |
nvme0 | (swap) | 128 | swap | |
nvme0 | / | 1408 | btrfs | |
nvme0 | /tmp | 256 | btrfs | |
nvme0 | /var/tmp | 256 | btrfs | Only system temp files |
nvme1 | /scratch | 2048 | btrfs | Ultra-fast scratch |
nvme2 | /lake | 2048 | btrfs | Fast shared data |
nvme3 | /home | 2048 | btrfs | User files |
sda,sdb | /stock | 8192 | btrfs | Frozen data (raid 0) |
sdc1 | /bakroot | 2048 | btrfs | dd of / |
sdc2 | /baklake | 2048 | btrfs | dd of /lake |
sdc3 | /bakhome | 2048 | btrfs | dd of /home |
Update and reboot¶
sudo apt update && reboot
sudo dnf update && reboot
Enable kernel modules¶
Run
sudo modprobe sha256
Set mount options¶
- Add
noatime
everywhere. Access timestamps (atime) are written using the default option,relatime
. This makes a lot of otherwise-unnecessary writes, degrading performance. - Add
noacl
everywhere. There’s probably no performance gain to disable ACL, but you almost definitely don’t need it. - Add
noexec
,nodev
, andnosuid
to/tmp
and/var/tmp
(if they exist).
Consider compression.¶
btrfs can compress data at rest and in transit. Whether to use lzo, zstd, or no compression depends primarily on the (uncompressed) throughput: Use heavier compression to compensate for slow IO, and use lighter compression for fast IO. Use no compression if the CPU is already the bottleneck. See benchmarks for btrfs compression. Here are my recommendations:
compression=off
for NVMe 2.0 drives connected directly to CPU lanes.compression=lzo
for all other NVMe drives.compression=lzo
for SATA-connected SSDs.compression=zstd:3
for SATA-connected HDDs.compression=zstd:3
for USB-connected drives.
Bug
Sometimes filesystems cannot be mounted with compress
, presumably for any number of reasons.
Warning
Make sure to follow the steps below to verify that your fstab
is valid and useable.
Edit fstab
¶
Following these rules, the fstab
for “Example scheme 1 – single-user workstation” might look like this:
# filesystem mount type options d p
.../by-uuid/... none swap sw 0 1
.../by-uuid/... /boot/efi vfat defaults 0 1
.../by-uuid/... /tmp btrfs noatime,noacl,noexec,nodev,nosuid 0 1
.../by-uuid/... /var/tmp btrfs noatime,noacl,noexec,nodev,nosuid 0 1
.../by-uuid/... / btrfs noatime,noacl 0 1
.../by-uuid/... /data btrfs noatime,noacl 0 1
.../by-uuid/... /docs btrfs noatime,noacl,compress=lzo 0 1
.../by-uuid/... /bak btrfs noatime,noacl,compress=zstd:3 0 1
Before rebooting, verify that your changes are probably ok by running
mount --fake --all --verbose
and
sudo systemctl daemon-reload
sudo findmnt --fstab --verify --verbose
Then reboot and see the results by running
cat /etc/mtab
Install packages¶
Open a terminal and enter the following commands to install the necessary packages:
First, enable the Universe repository:
sudo add-apt-repository universe -y
sudo apt install -y git vim curl wget xz-utils brotli lzma zstd iotop exa
sudo apt install libncurses-dev
sudo apt install -y build-essential cmake
sudo apt install -y zsh
sudo dnf update && upgrade
sudo dnf install -y git vim curl wget xz-utils brotli lzma zstd iotop exa
sudo dnf install -y ncurses-devel
sudo dnf install -y make automake gcc gcc-c++ kernel-devel cmake
sudo dnf install -y zsh
Install the GitHub CLI per the official GH Linux install instructions.
Set up firewall¶
sudo ufw enable
Fedora should come with firewalld
installed and enabled by default.
Allow SSH login¶
Install ssh to allow for remote logins.
sudo apt update
sudo apt install openssh-server
sudo ufw allow 22
Cosmetics/UI¶
Exa and Nerd fonts¶
Download one or more Nerd fonts. Then run
cd ~/Downloads # (1)!
for f in *.zip; do sudo unzip $f -d /usr/local/share/fonts; done
fc-cache
- Or wherever your downloaded Nerd fonts are
Set your terminal font to the Nerd font. (In Tilix, this is a per-profile setting called “Custom font”.) Now you can run
exa --icons
GNOME¶
In GNOME’s settings, set the time format to 24-hour and make sure Automatic Data and Time is selected. Also install extensions:
sudo apt install gnome-browser-connector
sudo dnf install gnome-browser-connector
Then open https://extensions.gnome.org/ and install the browser extension. I recommend installing:
- Force Quit
- Panel Date Format After installing, run
dconf write /org/gnome/shell/extensions/panel-date-format/format "'%Y-%m-%d %H:%M'"
Install Oh My Zsh¶
You’ll thank me later. (You’ll need ZSH installed for this to work.)
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
You should be prompted to change your shell. If you are not, run
chsh -s $(which zsh)
Make sure it is set by running
sudo cat /etc/passwd | grep ${USER}
You may need to reboot for the change to your login shell to take effect. You should now have a colorful shell, complete with a plugin for Git.
.commonrc
file¶
To keep the config for ZSH and Bash consistent, add a file called .commonrc
in your home directory:
echo 'export PATH=/usr/local/sbin:$PATH\n' > ~/.commonrc
echo 'source ~/.commonrc\n' >> ~/.zshrc
echo 'source ~/.commonrc\n' >> ~/.bashrc
From here on, only modify .commonrc
so that both Bash and ZSH have the same environment.
Git, SSH, and GPG¶
See this guide.
Install Java and Rust¶
First, Install the Rust toolchain.
Then, download JDK 21 from Temurin. Do not use Java 8, java.com, or OpenJDK. Make sure it’s on your $PATH
by running java --version
in a new shell.
Generate a certificate¶
If you need a certificate, set a static IP address and generate a certificate with certbot. Choose “None of the above” for Software. Then follow the instructions exactly, including the “Automating renewal” section. This may not work through some company and university firewalls.
Sudoers¶
The easiest way is to run
su #(1)!
usermod -aG sudo $USER
- This will require you to enter the root password.
See this sudoers guide for more info.
Dotfiles¶
See awesome-dotfiles. Here are some I used:
# xdg-open occasionally assumed in scripts,
# so aliasing it to macOS's `open` is a good idea
# alias xdg-open=open
# These improve safety
# Accidentally running `chown -R xx . /` (on root) can brick your system
# The same goes for chmod and chgrp
alias chown='chown --preserve-root'
alias chmod='chmod --preserve-root'
alias chgrp='chgrp --preserve-root'
alias wgetc='wget -c'
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# list open file handles for the current shell session (also see lsof)
alias handles='ls -la /proc/$$/fd'
# Check free memory
alias fre='free --human'
# Check CPU, memory, and swap usage
alias usg='vmstat --active'
# Check IO usage
alias iousg='sudo iotop --only --batch'
# List listening sockets
alias lssockets='sudo --listening --processes'
alias lstcp='sudo --listening --processes --tcp'
alias lsudp='sudo --listening --processes --udp'
# List threads
# -A == all processes
# -f == full listing (show args)
# -L == show threads
# -l == long format
# -y == Hide flags and show resident set size (RSS; memory used) instead of addr
# --headers == repeat header line once per page
# In the output:
# - NLWP is # of threads
# - LWP is "light-weight process"
alias threads='ps -A -f -L -l -y -S --headers'
# Normal grid exa (--created, --modified, and --git have no effect unless we pass --list)
alias e='exa --all --sort=name --group-directories-first --icons --created --modified --git'
# Detailed view with --list
alias el='exa --all --sort=name --group-directories-first --icons --created --modified --git --list'
# Detailed view in a grid (for wide monitors)
alias elg='exa --all --sort=name --group-directories-first --icons --created --modified --git --list --grid'
# These are nice as navigation shorthands
alias cd..='cd ..'
alias ..='cd ..'
alias ...='cd ../../../'
alias ....='cd ../../../../'
alias .....='cd ../../../../'
# make a dir and cd to it
function mkcd {
mkdir "$1" && cd "$1"
}
# This one chowns recursively for you
function grab() {
sudo chown -R ${USER}:${USER} ${1:-.}
}
# This one's modified from https://serverfault.com/questions/3743/what-useful-things-can-one-add-to-ones-bashrc
function extract () {
if [[ ! -f "$1" ]] ; then
>&2 echo "'$1' is not a file"
exit 2
fi
case "$1" in
*.tar.bz2) tar xvjf "$1" ;;
*.tar.gz) tar xvzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xvf "$1" ;;
*.tbz2) tar xvjf "$1" ;;
*.tgz) tar xvzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.snappy) snunzip "$1" ;;
*.sz) snunzip "$1" ;;
*.br) brotli -d "$1" ;;
*.xz) unxz "$1" ;;
*.lz4) unlz4 "$1" ;;
*.lzma) unlzma "$1" ;;
*.zst) unzstd "$1" ;;
*.7z) 7z x "$1" ;;
*) >&2 echo "I don't know how to extract '$1'"; exit 1 ;;
esac
}
Thanks
Thank you to Cole Helsell for drafting this guide with me.