Skip to content

Instantly share code, notes, and snippets.

@randallb
Last active September 5, 2025 17:32
Show Gist options
  • Save randallb/1258c61246ec801f282688c53b62c0a7 to your computer and use it in GitHub Desktop.
Save randallb/1258c61246ec801f282688c53b62c0a7 to your computer and use it in GitHub Desktop.
rbpara Mac Bootstrap Script
#!/bin/bash
# Bootstrap script for setting up a fresh Mac with rbpara
# Last updated: 2025-09-05 13:32:29 EDT
set -e
echo "πŸš€ rbpara Mac Bootstrap"
echo "======================="
echo ""
# Check if we're on macOS
if [[ "$OSTYPE" != "darwin"* ]]; then
echo "❌ This script is for macOS only"
exit 1
fi
# Step 1: Install Rosetta 2 if on Apple Silicon
if [[ $(uname -m) == "arm64" ]]; then
echo "πŸ”„ Checking for Rosetta 2..."
if ! pkgutil --pkg-info=com.apple.pkg.RosettaUpdateAuto &> /dev/null; then
echo "πŸ“¦ Installing Rosetta 2 for x86_64 compatibility..."
softwareupdate --install-rosetta --agree-to-license
echo "βœ… Rosetta 2 installed"
else
echo "βœ… Rosetta 2 is already installed"
fi
fi
# Step 2: Install Determinate Nix if needed
if ! command -v nix &> /dev/null; then
echo "πŸ“¦ Installing Determinate Nix..."
echo "Downloading the official installer..."
# Download the installer package
INSTALLER_PATH="/tmp/DeterminateNix.pkg"
curl -L --progress-bar https://install.determinate.systems/determinate-pkg/stable/Universal -o "$INSTALLER_PATH"
echo "Opening installer (you may need to enter your password)..."
# Open the installer and wait for completion
open -W "$INSTALLER_PATH"
# Clean up
rm -f "$INSTALLER_PATH"
# Source nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
# Verify installation
if ! command -v nix &> /dev/null; then
echo "❌ Nix installation appears to have failed or was cancelled"
echo "Please try running the script again or install manually from:"
echo "https://determinate.systems/posts/determinate-nix-installer"
exit 1
fi
echo "βœ… Nix installed successfully!"
else
echo "βœ… Nix is already installed"
fi
# Step 3: Install required tools temporarily
echo ""
echo "πŸ“¦ Installing required tools temporarily..."
echo ""
# Install all required tools to the default profile
# They'll be properly installed via nix-darwin later
nix profile install nixpkgs#sapling nixpkgs#gh nixpkgs#git nixpkgs#direnv
echo "πŸ“‚ Setting up rbpara..."
# Check if we're already in rbpara
if [ -f "bootstrap.sh" ]; then
echo "βœ… Already in rbpara directory"
RBPARA_DIR=$(pwd)
else
# Ensure GitHub CLI is authenticated
if ! gh auth status &>/dev/null; then
echo "πŸ”‘ Setting up GitHub authentication..."
echo "You'll need to authenticate with GitHub to clone the repository."
gh auth login --git-protocol https
else
echo "βœ… Already authenticated with GitHub"
fi
# Clone rbpara using Sapling
RBPARA_DIR="$HOME/code/rbpara"
if [ ! -d "$RBPARA_DIR" ]; then
echo "πŸ”„ Cloning rbpara with Sapling..."
mkdir -p "$HOME/code"
cd "$HOME/code"
sl clone https://github.com/randallb/rbpara.git rbpara
else
echo "βœ… rbpara already exists at $RBPARA_DIR"
fi
cd "$RBPARA_DIR"
fi
# Step 4: Install Homebrew if needed
echo ""
echo "🍺 Checking for Homebrew..."
if ! command -v brew &> /dev/null; then
echo "πŸ“¦ Installing Homebrew..."
# Clean up any leftover tap references before installing
rm -rf /opt/homebrew/Library/Taps/randallb/homebrew-rbpara 2>/dev/null || true
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add Homebrew to PATH for this session (M1/M2 Macs use /opt/homebrew)
if [[ -f "/opt/homebrew/bin/brew" ]]; then
echo " Adding Homebrew to PATH (/opt/homebrew)..."
eval "$(/opt/homebrew/bin/brew shellenv)"
export PATH="/opt/homebrew/bin:$PATH"
elif [[ -f "/usr/local/bin/brew" ]]; then
echo " Adding Homebrew to PATH (/usr/local)..."
eval "$(/usr/local/bin/brew shellenv)"
export PATH="/usr/local/bin:$PATH"
fi
# Verify brew is now available
if ! command -v brew &> /dev/null; then
echo "❌ Homebrew installation failed or not in PATH"
echo " Please install manually and re-run this script"
exit 1
fi
echo "βœ… Homebrew installed and available"
else
echo "βœ… Homebrew is already installed"
# Clean up any leftover tap references
brew untap randallb/rbpara 2>/dev/null || true
rm -rf /opt/homebrew/Library/Taps/randallb/homebrew-rbpara 2>/dev/null || true
# Make sure brew is in PATH even if already installed
if [[ -f "/opt/homebrew/bin/brew" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -f "/usr/local/bin/brew" ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
fi
# Skip homebrew tap setup for now
# echo ""
# echo "🍺 Setting up custom Homebrew tap..."
# if [ ! -d "$RBPARA_DIR/config/homebrew-tap/.git" ]; then
# cd "$RBPARA_DIR/config/homebrew-tap"
# git init
# git add .
# git commit -m "Initial custom casks"
# cd "$RBPARA_DIR"
# fi
# Step 5: Set username if needed
echo ""
echo "πŸ‘€ Setting up username..."
CURRENT_USER=$(whoami)
echo " Detected username: $CURRENT_USER"
# Update all config files with the current username
"$RBPARA_DIR/bin/set-username" "$CURRENT_USER"
# Configure git user (needed for homebrew and other tools)
echo ""
echo "πŸ”§ Configuring Git user..."
git config --global user.name "Randall Bennett"
git config --global user.email "[email protected]"
echo "βœ… Git user configured"
# Step 6: Set hostname
echo ""
echo "πŸ’» What should this computer be called?"
echo " (e.g., 'work-laptop', 'personal-macbook', etc.)"
read -p "Computer name: " COMPUTER_NAME
if [ -z "$COMPUTER_NAME" ]; then
echo " No name provided, keeping existing hostname"
else
echo " Setting hostname to: $COMPUTER_NAME"
sudo scutil --set ComputerName "$COMPUTER_NAME"
sudo scutil --set LocalHostName "$COMPUTER_NAME"
sudo scutil --set HostName "$COMPUTER_NAME.bflocal"
echo "βœ… Hostname configured"
echo " Computer name: $COMPUTER_NAME"
echo " Local hostname: $COMPUTER_NAME"
echo " Network hostname: $COMPUTER_NAME.bflocal"
fi
# Step 7: Choose configuration type
echo ""
echo "πŸ€” Which configuration would you like to install?"
echo ""
echo "1) Full - All applications and tools (recommended for primary machine)"
echo "2) Lite - Minimal setup (good for testing or secondary machines)"
echo ""
read -p "Enter your choice (1 or 2): " CONFIG_CHOICE
case $CONFIG_CHOICE in
1)
CONFIG_TYPE="full"
echo "βœ… Selected: Full configuration"
;;
2)
CONFIG_TYPE="lite"
echo "βœ… Selected: Lite configuration"
;;
*)
echo "Invalid choice. Defaulting to full configuration."
CONFIG_TYPE="full"
;;
esac
# Save the configuration choice
echo "$CONFIG_TYPE" > "$RBPARA_DIR/.nix-config-type"
echo "πŸ’Ύ Configuration choice saved to .nix-config-type"
# Step 8: Build and apply system configuration
echo ""
echo "🍎 Setting up nix-darwin and home-manager..."
cd "$RBPARA_DIR/config/nix/system"
echo "πŸ”¨ Building $CONFIG_TYPE configuration..."
nix build ".#darwinConfigurations.$CONFIG_TYPE.system"
echo "🎯 Applying $CONFIG_TYPE configuration..."
sudo ./result/sw/bin/darwin-rebuild switch --flake ".#$CONFIG_TYPE"
# Step 9: Set up direnv for the development environment
echo ""
echo "πŸ“ Setting up development environment..."
cd "$RBPARA_DIR"
direnv allow
# Step 10: Run rebuild again to ensure dock is properly configured
echo ""
echo "πŸ”„ Running final rebuild to ensure everything is configured..."
cd "$RBPARA_DIR"
# Source direnv to get the environment
eval "$(direnv export bash)"
bin/rebuild
echo "βœ… Final configuration applied"
echo ""
echo "✨ Bootstrap complete!"
echo ""
echo "Next steps:"
echo "1. Update your email in config/nix/system/home.nix"
echo "2. Restart your terminal or run: source ~/.zshrc"
echo "3. cd ~/code/rbpara"
echo "4. The dev environment should auto-activate via direnv"
echo "5. Configure Sapling: sl config ui.username 'Your Name <[email protected]>'"
echo "6. Restore app preferences: bin/sync-prefs"
# Step 11: Clean up temporary tools
echo ""
echo "🧹 Cleaning up temporary tools..."
# Remove the temporarily installed tools (they'll be installed properly via nix-darwin)
echo "Note: You may see 'error: package does not exist' - this is normal"
nix profile remove nixpkgs#sapling nixpkgs#gh 2>/dev/null || true
echo "βœ… Cleanup complete"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment