#!/usr/bin/env bash # =========================================================================== # Linux Machine Provisioning — Master Orchestrator # =========================================================================== # Usage: # bash provision.sh --all # Run all stages in order # bash provision.sh --stage # 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 " 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 " ;; *) echo "Usage:" echo " bash provision.sh --all # Run everything" echo " bash provision.sh --stage # Run one stage" echo " bash provision.sh --list # List stages" echo " source provision.sh --interactive # Load for manual use" exit 1 ;; esac } main "$@"