Skip to content

Instantly share code, notes, and snippets.

@hartmantis
Last active February 9, 2023 06:22
Show Gist options
  • Save hartmantis/a0e417068f6148bac4ee343e8b411977 to your computer and use it in GitHub Desktop.
Save hartmantis/a0e417068f6148bac4ee343e8b411977 to your computer and use it in GitHub Desktop.
macOS bootstrap script
#!/bin/bash
#
# Provisioning script for a new macOS Big Sur machine.
# To bootstrap a brand new box:
# * Build a bootable USB installer drive:
# - Partition a USB flash drive as appropriate
# - On an existing macOS box, search the App Store for "Big Sur"
# - Download macOS and wait for the installer screen to pop up
# - Build the install media:
# sudo /Applications/Install\ macOS\ Big\ Sur.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
# * Boot the new machine and hold the Option key until it gives you the option to boot from the USB drive
# * Partition the boot drive as desired (I use APFS, case-sensitive)
# * Install macOS
# * Run through the iCloud, user creation, Apple Wallet, etc. setup of the initial boot
# * Run this script:
# bash -c "$(curl -fsSL https://gist.githubusercontent.com/RoboticCheese/a0e417068f6148bac4ee343e8b411977/raw/9ab9412a89ab0bfecf5a227d95b972d044a5d1ad/macos_bootstrap.sh)"
#
#
# TODO:
# - [ ] It doesn't pause the Homebrew install, but adobe-digital-editions throws up a dialog to allow access to the Documents folder then opens the app when granted
# - [ ] Ditto Zoom and the Downloads folder
# - [ ] Set my external monitor to scaled resolution and max desktop space
# - [ ] Set displays to bridged instead of mirrored
# - [ ] Install my favorite VSCode extensions
# - [ ] Reassign Cmd+Space to Alfred instead of Spotlight
# - [ ] Set up apps to start at login that don't do it on their own (Docker? Magnet? PIA?)
# - [ ] Box's extension needs to be granted access
# - [ ] Ditto VirtualBox's system extension
# - [ ] Reboot so Box's extension can take effect
# - [ ] Install DeDRM in Calibre
# - [ ] "Cask 'yubico-yubikey-manager' is unavailable: No Cask with this name exists."
# - [ ] Grant full disk access to Terminal, iTerm2, and Hyper(?)
# - [ ] Enable the 1Blocker and 1Password extensions in Safari
# - [ ] Run the PIA installer
set -e
# The initial sudo command will authorize this user and temporarily remove the 5min sudo timeout
sudo sh -c 'echo "Defaults timestamp_timeout=-1" > /private/etc/sudoers.d/disable_timeout'
# Grant user write access to man8??? Is this really needed?
# sudo chown -R $(whoami) /usr/local/share/man/man8
echo
echo "##########################################"
echo "# Installing macOS command line tools... #"
echo "##########################################"
echo
# Borrowed from the Chef build-essential cookbook and updated for Big Sur
touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
PROD=$(softwareupdate -l | grep "\* Label: Command Line Tools for Xcode" | tail -n 1 | sed 's/^\* Label: //')
softwareupdate -i "$PROD" --verbose
rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
echo
echo "###########################"
echo "# Installing oh-my-zsh... #"
echo "###########################"
echo
/bin/sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
echo
echo "############################################"
echo "# Setting up dot directories for Dropbox...#"
echo "############################################"
echo
for D in .aws .chef .gitconfig .gnupg .ssh .stove .zprofile; do
rm -rf "${HOME}/${D}"
ln -s "${HOME}/Dropbox/Home/${D}" "${HOME}/${D}"
done
echo
echo "#################################"
echo "# Configuring the macOS Dock... #"
echo "#################################"
echo
defaults write com.apple.dock autohide -bool true # Auto-hide the Dock
defaults write com.apple.dock magnification -bool true # Magnify icons on mouseover
defaults write com.apple.dock wvous-bl-corner -int 5 # Mouse to bottom left to start screensaver
defaults write com.apple.dock wvous-bl-modifier -int 0
killall Dock # Make the new settings take effect
echo
echo "##########################"
echo "# Installing Homebrew... #"
echo "##########################"
echo
# Homebrew cannot be run as root, requires sudo access, and needs an environment variable to not prompt the user to press enter
CI=true /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
# If this is new Homebrew, it needs some path help.
# Our .zprofile is in Dropbox but .bash_profile isn't.
if [ -d /opt/homebrew ]; then
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> "${HOME}/.bash_profile"
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
# Turn off Homebrew analytics
brew analytics off
echo
echo "###############################"
echo "# Installing Homebrew apps... #"
echo "###############################"
echo
mkdir "${HOME}/.homebrew"
cat > "${HOME}/.homebrew/Brewfile" <<- EOM
# TBD:
# brew 'ballerina' # The Ballerina language depends on an ancient OpenJDK 8
# brew 'garden-cli' # The Garden.io Kubernetes app lifecycle looks cool but I never used it
# cask 'avira-antivirus' # Doesn't support Big Sur yet
# cask 'chef-workstation' # Replace with either nothing or Cinc
# cask 'dropbox' # Maestral is better and has Arm support
# cask 'spectrum' # Was I using this chat app for anything?
# cask 'vagrant' # Doesn't support Arm
# cask 'virtualbox' # Probably won't ever support Arm
# mas 'Divvy', id: 413857545 # Magnet seems a better window manager
# mas 'Edison Mail', id: 1489591003 # Been just using Outlook lately
# mas 'Spark', id: 1176895641 # Been just using Outlook lately
# Taps that we use:
tap 'habitat-sh/habitat' # Chef Habitat
tap 'hashicorp/tap' # Hashicorp's various products
tap 'homebrew/cask' # Cask support
# Regular Homebrew apps:
brew 'aws-cdk' # The AWS Cloud Development Kit
brew 'awscli' # The AWS CLI
brew 'cfssl' # CloudFlare's PKI toolkit
brew 'doctl' # The DigitalOcean CLI
brew 'gh' # The GitHub CLI
brew 'git' # Get a newer version of Git than what's in macOS
brew 'go' # The Go programming language
brew 'hab' # Habitat by Chef (To be replaced when Cinc Packager is released)
brew 'helm' # The Helm Kubernetes package manager
brew 'httpie' # The httpie more user-friendly alternative to curl
brew 'hub' # The Hub command line extensions for Git
brew 'hugo' # The Hugo static site generator
brew 'jq' # Helpful JSON parsing CLI tool
brew 'kubernetes-cli' # The Kubernetes CLI
brew 'linkerd' # The CLI for the Linkerd service mesh
brew 'mas' # CLI for installing App Store apps
brew 'minikube' # The Minikube local Kubernetes cluster utility
brew 'node' # Node.js
brew 'nomad' # Hashicorp Nomad
brew 'obs' # OBS
brew 'openapi-generator' # Generator tool for OpenAPI specs
brew 'packer' # Hashicorp Packer
brew 'pre-commit' # Git pre-commit hooks
brew 'python' # A newer Python than what's in macOS
brew 'ruby' # A newer Ruby than what's in macOS
brew 'rust' # The Rust programming language
brew 'shellcheck' # The ShellCheck linter for Bash scripts
brew 'step' # SmallStep crypto and x509 swiss-army-knife
brew 'telnet' # macOS doesn't include a Telnet client
brew 'terraform' # Hashicorp Terraform
brew 'tig' # The Tig utiility for Git
brew 'tmux' # The terminal multiplexer
brew 'wget' # macOS doesn't include wget
brew 'zola' # The Zola (formerly Gutenberg) static site generator
# Homebrew casks:
# cask 'adobe-digital-editions' # For ePub library books; not Arm native yet
cask 'alfred' # Alfred still > Spotlight
cask 'authy' # MFA utility
cask 'balenaetcher' # Tool for making bootable flash drive OS images
# cask 'box-drive' # Box.com macOS Finder integration; not Arm native yet
cask 'calibre' # Calibre ebook utility
cask 'canva' # Graphical video tool
cask 'dash' # Dash documentation tool
cask 'discord' # Discord chat app
cask 'docker' # Docker!
# cask 'elgato-camera-hub' # Configures the Elgato FaceCam; not Arm native yet
cask 'firefox' # Firefox browser
cask 'github' # GitHub desktop client
cask 'google-chrome' # Chrome browser
cask 'google-cloud-sdk' # Google Cloud SDK
cask 'gpg-suite' # GPG key management tools
cask 'hyper' # An alternative, Electron-based terminal
# cask 'inspec' # Chef's Inspec testing utility; not Arm native yet
cask 'iterm2' # The iTerm2 alt terminal
cask 'lastfm' # For scrobbling songs from iTunes
cask 'maestral' # Third-party Dropbox app with Arm support
# cask 'mattermost' # Open source fork of a Slack knockoff; do I need this anymore?
cask 'microsoft-office' # Office 365
# cask 'microsoft-teams' # Microsoft Teams; not Arm native
# cask 'multipass' # Canonical's lightweight VM manager; do I need this?
cask 'parallels' # Parallels VM manager
cask 'paw' # Paw API utility
cask 'philips-hue-sync' # Philips Hue light controller tool
cask 'powershell' # Microsoft PowerShell
cask 'private-internet-access' # PIA VPN client
cask 'retroarch-metal' # RetroArch game emulator platform
cask 'session-manager-plugin' # The session manager plugin for the AWS CLI
cask 'spotify' # Spotify!
cask 'steam' # Steam!
cask 'telegram' # Telegram messenger
# cask 'utm' # macOS frontend for QEMU; do I need this?
cask 'viscosity' # General purpose VPN client
cask 'visual-studio-code' # VS Code
cask 'vlc' # VLC video player
cask 'yacreader' # Comic book reader app
cask 'yubico-yubikey-manager' # Management app for Yubikeys
cask 'zoom' # Zoom video conference app
# App Store apps:
mas '1Blocker', id: 1365531024 # Ad blocker for Safari
mas '1Password 7', id: 1333542190 # 1Password password manager
mas 'Fantastical', id: 975937182 # Calendar tool
mas 'GarageBand', id: 682658836 # Apple GarageBand
mas 'GIPHY CAPTURE', id: 668208984 # GIF screen capture tool
mas 'iMovie', id: 408981434 # Apple iMovie
mas 'Keynote', id: 409183694 # Apple Keynote
mas 'Kindle', id: 405399194 # Amazon Kindle app
mas 'Magnet', id: 441258766 # Fancy window manager
mas 'Markdown Pro', id: 465965038 # Visual Markdown editor
mas 'Numbers', id: 409203825 # Apple Numbers
mas 'Pages', id: 409201541 # Apple Pages
mas 'Slack', id: 803453959 # Slack
mas 'Tweetbot', id: 1384080005 # The best Twitter client
mas 'WiFi Explorer', id: 494803304 # Wi-Fi network exploration
mas 'Xcode', id: 497799835 # Apple Xcode
EOM
pushd "${HOME}/.homebrew" || exit 1
brew bundle
popd || exit 1
# Kill apps that Homebrew starts but don't need to be running
killall Adobe\ Digital\ Editions
killall zoom.us
echo
echo "#####################################################"
echo "# Starting up apps that should always be running... #"
echo "#####################################################"
echo
# open /Applications/Alfred.app
# open /Applications/Box.app
# open /Applications/Docker.app
# open /Applications/Dropbox.app
# open Private Internet Access
echo
echo "#####################################"
echo "# Configuring Visual Studio Code... #"
echo "#####################################"
echo
# Disable sending telemetry data to Microsoft
# Install all the extensions we use
code --install-extension hashicorp.terraform
code --install-extension amazonwebservices.aws-toolkit-vscode
code --install-extension ms-toolsai.jupyter
code --install-extension ms-python.python
# Restore the default 5min sudo timeout
sudo rm /private/etc/sudoers.d/disable_timeout
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment