Initial commit: linux-provision repo

Distribution-agnostic provisioning script that sets up a new Linux machine
(Detected via lib/distro.sh - supports Debian/Ubuntu/Pop and Fedora families).

13 stages covering:
- System packages, external repos, toolchains (nvm, uv, Python)
- Shell config (zsh, oh-my-zsh, p10k), git, SSH
- Custom uv tools from ~40 git repos
- Desktop config (keybindings, hotkeys, ghostty, fonts)
- Docker, system tweaks, browser/app installs
- Custom systemd user services (porridge, swayidle, mempi-sync, etc.)
- API keys loaded from Bitwarden at shell startup
This commit is contained in:
2026-06-05 21:21:46 +10:00
commit 180c5838ea
36 changed files with 4176 additions and 0 deletions

209
stages/01-repos.sh Normal file
View File

@@ -0,0 +1,209 @@
#!/usr/bin/env bash
# ===========================================================================
# Stage 01: Third-Party Repositories
# Adds external package repos. Completely different per distro family.
#
# Debian/Ubuntu/Pop: uses PPAs and .list/.sources files in
# /etc/apt/sources.list.d/
# Fedora: uses .repo files in /etc/yum.repos.d/ and COPRs
# ===========================================================================
# ==================================================================
# COMMON: Add GPG keys (shared helper)
# ==================================================================
add_gpg_key() {
local url="$1"
local dest="$2"
if [ ! -f "$dest" ]; then
sudo curl -fsSL "$url" -o "$dest" 2>/dev/null || {
warn "Failed to download GPG key: $url"
return 1
}
sudo chmod 644 "$dest"
fi
}
# ==================================================================
# DEBIAN / UBUNTU / POP — APT-based
# ==================================================================
if [ "$DISTRO_FAMILY" = "debian" ]; then
info "Configuring APT repositories..."
# ---- VS Code ----
info " Adding VS Code repo..."
if [ ! -f /etc/apt/sources.list.d/vscode.sources ]; then
add_gpg_key "https://packages.microsoft.com/keys/microsoft.asc" \
"/usr/share/keyrings/microsoft.gpg"
cat << 'EOF' | sudo tee /etc/apt/sources.list.d/vscode.sources > /dev/null
Types: deb
URIs: https://packages.microsoft.com/repos/code
Suites: stable
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/microsoft.gpg
EOF
ok " VS Code repo added."
fi
# ---- Google Chrome ----
info " Adding Google Chrome repo..."
if [ ! -f /etc/apt/sources.list.d/google-chrome.sources ]; then
add_gpg_key "https://dl.google.com/linux/linux_signing_key.pub" \
"/usr/share/keyrings/google-chrome.gpg"
cat << 'EOF' | sudo tee /etc/apt/sources.list.d/google-chrome.sources > /dev/null
Types: deb
URIs: https://dl.google.com/linux/chrome/deb/
Suites: stable
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/google-chrome.gpg
EOF
ok " Google Chrome repo added."
fi
# ---- Docker CE ----
info " Adding Docker CE repo..."
if [ ! -f /etc/apt/sources.list.d/docker.list ]; then
add_gpg_key "https://download.docker.com/linux/${DISTRO_ID}/gpg" \
"/etc/apt/keyrings/docker.asc"
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/${DISTRO_ID} ${DISTRO_VERSION_CODENAME:-$(. /etc/os-release && echo "$VERSION_CODENAME")} stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
ok " Docker CE repo added."
fi
# ---- Tailscale ----
info " Adding Tailscale repo..."
if [ ! -f /etc/apt/sources.list.d/tailscale.list ]; then
add_gpg_key "https://pkgs.tailscale.com/stable/${DISTRO_ID}/$(. /etc/os-release && echo "$VERSION_CODENAME").gz" \
"/usr/share/keyrings/tailscale-archive-keyring.gpg" 2>/dev/null || \
add_gpg_key "https://pkgs.tailscale.com/stable/${DISTRO_ID}/repo.gpg" \
"/usr/share/keyrings/tailscale-archive-keyring.gpg"
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/${DISTRO_ID} $(. /etc/os-release && echo "$VERSION_CODENAME") main" | \
sudo tee /etc/apt/sources.list.d/tailscale.list > /dev/null
ok " Tailscale repo added."
fi
# ---- Signal Desktop ----
info " Adding Signal repo..."
if [ ! -f /etc/apt/sources.list.d/signal-desktop.sources ]; then
add_gpg_key "https://updates.signal.org/desktop/apt/keys.asc" \
"/usr/share/keyrings/signal-desktop-keyring.gpg"
cat << 'EOF' | sudo tee /etc/apt/sources.list.d/signal-desktop.sources > /dev/null
Types: deb
URIs: https://updates.signal.org/desktop/apt
Suites: xenial
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/signal-desktop-keyring.gpg
EOF
ok " Signal repo added."
fi
# ---- Papirus icon theme (PPA) ----
info " Adding Papirus PPA..."
if [ ! -f /etc/apt/sources.list.d/papirus-ubuntu-papirus-*.sources ]; then
$REPO_ADD_PPA papirus/papirus 2>/dev/null && ok " Papirus PPA added." || warn " Papirus PPA failed."
fi
# ---- Solaar (Logitech) PPA ----
info " Adding Solaar PPA..."
if [ ! -f /etc/apt/sources.list.d/solaar-unifying-ubuntu-stable-*.sources ]; then
$REPO_ADD_PPA solaar-unifying/stable 2>/dev/null && ok " Solaar PPA added." || warn " Solaar PPA failed."
fi
# ---- Ghostty terminal PPA ----
info " Adding Ghostty PPA..."
$REPO_ADD_PPA ghostty/ghostty 2>/dev/null && ok " Ghostty PPA added." || warn " Ghostty PPA failed."
# ---- Zotero repo ----
info " Adding Zotero repo..."
if [ ! -f /etc/apt/sources.list.d/zotero.list ]; then
add_gpg_key "https://zotero.retorque.re/file/apt-package-archive/pubkey.gpg" \
"/usr/share/keyrings/zotero-archive-keyring.gpg"
echo "deb [signed-by=/usr/share/keyrings/zotero-archive-keyring.gpg by-hash=force] https://zotero.retorque.re/file/apt-package-archive ./" | \
sudo tee /etc/apt/sources.list.d/zotero.list > /dev/null
ok " Zotero repo added."
fi
# ---- Yubico PPA ----
info " Adding Yubico PPA..."
$REPO_ADD_PPA yubico/stable 2>/dev/null && ok " Yubico PPA added." || warn " Yubico PPA failed."
# ==================================================================
# FEDORA / RHEL — DNF-based
# ==================================================================
elif [ "$DISTRO_FAMILY" = "fedora" ]; then
info "Configuring DNF repositories..."
# ---- RPM Fusion (free + nonfree) ----
info " Enabling RPM Fusion..."
$PKG_INSTALL \
"https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" \
"https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm" \
2>/dev/null && ok " RPM Fusion configured." || warn " RPM Fusion install failed."
# ---- VS Code ----
info " Adding VS Code repo..."
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc 2>/dev/null || true
cat << 'EOF' | sudo tee /etc/yum.repos.d/vscode.repo > /dev/null
[code]
name=Visual Studio Code
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
EOF
ok " VS Code repo added."
# ---- Google Chrome ----
info " Adding Google Chrome repo..."
cat << 'EOF' | sudo tee /etc/yum.repos.d/google-chrome.repo > /dev/null
[google-chrome]
name=Google Chrome
baseurl=https://dl.google.com/linux/chrome/rpm/stable/x86_64
enabled=1
gpgcheck=1
gpgkey=https://dl.google.com/linux/linux_signing_key.pub
EOF
ok " Google Chrome repo added."
# ---- Docker CE ----
info " Adding Docker CE repo..."
$REPO_ADD_RPM https://download.docker.com/linux/fedora/docker-ce.repo 2>/dev/null && \
ok " Docker repo added." || warn " Docker repo add failed."
# ---- Tailscale ----
info " Adding Tailscale repo..."
$REPO_ADD_RPM https://pkgs.tailscale.com/stable/fedora/tailscale.repo 2>/dev/null && \
ok " Tailscale repo added." || warn " Tailscale repo add failed."
# ---- Signal Desktop ----
info " Adding Signal repo..."
cat << 'EOF' | sudo tee /etc/yum.repos.d/signal-desktop.repo > /dev/null
[signal-desktop]
name=Signal Desktop
baseurl=https://updates.signal.org/desktop/yum
enabled=1
gpgcheck=1
gpgkey=https://updates.signal.org/desktop/signal_pubkey.gpg
EOF
ok " Signal repo added."
# ---- COPRs for extra packages ----
# Papirus icon theme is in RPM Fusion nonfree.
# Solaar is in RPM Fusion.
# Yubico tools: use COPR
info " Adding COPR repos..."
# $REPO_ADD_COPR atim/papirus-icon-theme 2>/dev/null || true
# $REPO_ADD_COPR sergiomb/Solaar 2>/dev/null || true
# ---- Zotero — no DNF repo, use Flatpak (handled in stage 13) ----
info " Note: Zotero will be installed via Flatpak or tarball in stage 13."
fi
# ---- Update package cache after adding repos ----
info "Updating package cache..."
$PKG_UPDATE 2>/dev/null || warn "Package cache update had issues."
ok "Stage 01 complete: repositories configured."