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

101
stages/05-git.sh Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env bash
# ===========================================================================
# Stage 05: Git Configuration & SSH Keys
# Deploys .gitconfig and optionally generates SSH keys.
# ===========================================================================
# The Pop machine's .gitconfig is well-optimised:
# - SSH key signing (gpg.format = ssh)
# - zdiff3 conflict style, histogram diff algorithm
# - rerere.enabled, autoSquash, autoStash
# - push.autoSetupRemote, pull.rebase, fetch.prune
# ===========================================================================
CONFIG_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/config"
# ---- Deploy .gitconfig ----
info "Deploying .gitconfig..."
if [ -f "$HOME/.gitconfig" ]; then
cp "$HOME/.gitconfig" "$HOME/.gitconfig.bak.$(date +%Y%m%d)" 2>/dev/null
warn "Backed up existing .gitconfig"
fi
# Use the template from config/git/gitconfig
# NOTE: This template does NOT contain your signing key or email.
# Edit it after deployment to set:
# [user]
# name = Your Name
# email = your.email@example.com
# signingkey = <your-ssh-public-key>
cp "${CONFIG_DIR}/git/gitconfig" "$HOME/.gitconfig"
ok ".gitconfig deployed."
warn "REMINDER: Edit ~/.gitconfig to set your name, email, and signingkey."
# ---- Deploy .gitignore_global ----
info "Deploying global .gitignore..."
if [ -f "$HOME/.gitignore" ]; then
warn "Global .gitignore already exists (keeping)."
else
# A sensible global gitignore for common OS + editor files
cat > "$HOME/.gitignore" << 'EOF'
# OS files
.DS_Store
Thumbs.db
Desktop.ini
# Editor/IDE
*.swp
*.swo
*~
.vscode/
.idea/
*.sublime-*
# Python
__pycache__/
*.py[cod]
*.egg-info/
.venv/
.eggs/
# Node
node_modules/
.npm/
# Rust
target/
EOF
ok "Global .gitignore deployed."
fi
# ---- Git SSH key ----
# The Pop machine has a single SSH key: id_ed25519_github
# Loading is handled by bw-load-ssh.sh (stage 07) from Bitwarden.
# This stage can generate a new key if one doesn't exist.
info "Checking SSH keys..."
if [ ! -f "$HOME/.ssh/id_ed25519" ]; then
warn "No SSH key found."
warn "Options:"
warn " 1. Generate a new key (recommended for new machine):"
warn " ssh-keygen -t ed25519 -C 'hi@julianprester.com'"
warn " 2. Restore from backup/Bitwarden (see TODO.md)"
warn " 3. Skip for now (run bw-load-ssh.sh later to load from Bitwarden)"
echo ""
read -r -p "Generate a new SSH key now? [y/N] " response
if [[ "$response" =~ ^[Yy]$ ]]; then
ssh-keygen -t ed25519 -C "hi@julianprester.com" -f "$HOME/.ssh/id_ed25519" -N "" 2>/dev/null || {
warn "Key generation skipped or failed."
}
ok "SSH key generated: ~/.ssh/id_ed25519.pub"
cat "$HOME/.ssh/id_ed25519.pub"
warn "Add this key to GitHub: https://github.com/settings/keys"
fi
else
ok "SSH key already exists."
fi
# Ensure proper SSH permissions
chmod 700 "$HOME/.ssh" 2>/dev/null || true
find "$HOME/.ssh" -type f -name "id_*" -exec chmod 600 {} \; 2>/dev/null || true
find "$HOME/.ssh" -type f -name "*.pub" -exec chmod 644 {} \; 2>/dev/null || true
ok "Stage 05 complete: Git configured."