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

131
provision.sh Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env bash
# ===========================================================================
# Linux Machine Provisioning — Master Orchestrator
# ===========================================================================
# Usage:
# bash provision.sh --all # Run all stages in order
# bash provision.sh --stage <name> # Run a single stage
# bash provision.sh --list # List all stages
# source provision.sh --interactive # Source for manual calls
#
# Distribution-agnostic — detects Debian/Ubuntu/Pop/Fedora and adjusts
# package manager, repo config, etc. automatically.
# ===========================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
STAGES_DIR="${SCRIPT_DIR}/stages"
LIBS_DIR="${SCRIPT_DIR}/lib"
CONFIG_DIR="${SCRIPT_DIR}/config"
# ---- Source distro detection first ----
source "${LIBS_DIR}/distro.sh"
# ---- Colour helpers ----
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; }
# ---- Available stages ----
STAGES=(
"00-envcheck" # Environment checks (uses lib/distro.sh vars)
"01-repos" # Third-party repositories
"02-packages" # System packages
"03-toolchains" # nvm, Node, uv, Python
"04-shell" # Zsh, oh-my-zsh, p10k
"05-git" # Git config, SSH
"06-uv-projects" # Clone + install Julian's Python tools
"07-scripts" # ~/.local/bin custom scripts
"08-systemd" # User systemd services
"09-desktop" # Keybindings, hotkeys, desktop config
"10-docker" # Docker CE
"11-tweaks" # sysctl, kernel, TLP/powertop
"12-other-apps" # Chrome, Signal, Zotero
)
# ===========================================================================
# Stage Runner
# ===========================================================================
run_stage() {
local stage_name="$1"
local stage_file="${STAGES_DIR}/${stage_name}.sh"
if [ ! -f "$stage_file" ]; then
error "Stage script not found: ${stage_file}"
return 1
fi
info "=============================================="
info " Running stage: ${stage_name}"
info "=============================================="
source "$stage_file"
ok "Stage '${stage_name}' completed."
echo ""
}
# ===========================================================================
# Main
# ===========================================================================
main() {
local mode="${1:-}"
case "$mode" in
--all)
info "Starting full provisioning on ${DISTRO_ID} ${DISTRO_VERSION} (${DISTRO_FAMILY})"
info "You may be prompted for sudo password."
for stage in "${STAGES[@]}"; do
run_stage "$stage" || warn "Stage '${stage}' failed (continuing)."
done
ok "Provisioning complete!"
warn "Review TODO.md for manual post-install steps."
;;
--stage)
local target="${2:-}"
if [ -z "$target" ]; then
error "Usage: provision.sh --stage <stage-name>"
exit 1
fi
run_stage "$target"
;;
--list)
echo "Available stages (distro: ${DISTRO_ID} / ${DISTRO_FAMILY}):"
for stage in "${STAGES[@]}"; do
echo " ${stage}"
done
;;
--interactive)
info "Sourcing stage functions for interactive use."
for stage in "${STAGES[@]}"; do
local f="${STAGES_DIR}/${stage}.sh"
[ -f "$f" ] && source "$f"
done
info "Stages loaded. Call: run_stage <stage-name>"
;;
*)
echo "Usage:"
echo " bash provision.sh --all # Run everything"
echo " bash provision.sh --stage <name> # Run one stage"
echo " bash provision.sh --list # List stages"
echo " source provision.sh --interactive # Load for manual use"
exit 1
;;
esac
}
main "$@"