Skip to content

Instantly share code, notes, and snippets.

@coreyti
Created September 11, 2018 19:51
Show Gist options
  • Save coreyti/71ff8c99f6515f005ff47552122321cc to your computer and use it in GitHub Desktop.
Save coreyti/71ff8c99f6515f005ff47552122321cc to your computer and use it in GitHub Desktop.
gist.bootstrap (WIP)

macOS Bootstrap

Actions Taken that Need to be Scripted

  • Applications
    • "PlistEdit Pro" ... Check for updates automatically: true
    • "SizeUp" (installation and configuration: license, startup, accessibility)
    • "Zoom.us" app (installation and configuration)
    • "Viscosity" app (installation and configuration)
    • "Bartender" app (configuration ... defaults read com.surteesstudios.Bartender)
  • Settings
    • defaults read (get everything)
    • "Security & Privacy" ... "Allow your Apple Watch to unlock your Mac" com.apple.sharingd.plist? Also, might not want to do this, given the challenge and security implication.
    • "Mission Control" ... disable keyboard shortcuts for "Mission Control" and "Application Windows"
    • "Finder":
      • View option: "Always open in column view"
      • View option: "Arrange by kind"
      • Preference: Sidebar: "corey"
    • "Accessibility" ... Mouse & Trackpad --> Enable dragging

Stuff to Explore

  • Trackpad speed and click

  • "Ideal" git setup (e.g., aliases)

  • "Ideal" Atom.app setup

  • "Ideal" bash setup

    • No-repeat for history
    • bash-it with:
      • git
      • prompt (see Akela)
  • Primary desktop switcher (i.e. for app switcher and dock)

  • iTerm's "Load preferences from a custom folder or URL" (and how to implement similar for wip-backed apps and config)

  • https://github.com/kristovatlas/osx-config-check

  • 1Password w/ family setup

  • /usr/local/etc/bash_completion.d

  • [ ]

    A valid GOPATH is required to use the go get command. If $GOPATH is not specified, $HOME/go will be used by default: https://golang.org/doc/code.html#GOPATH

  • [ ]

    If builds of PostgreSQL 9 are failing and you have version 8.x installed, you may need to remove the previous version first. See: Homebrew/legacy-homebrew#2510

    To migrate existing data from a previous major version (pre-9.0) of > PostgreSQL, see: https://www.postgresql.org/docs/9.6/static/upgrading.html

    To migrate existing data from a previous minor version (9.0-9.5) of > PostgreSQL, see: https://www.postgresql.org/docs/9.6/static/pgupgrade.html

    You will need your previous PostgreSQL installation from brew to perform > pg_upgrade. Do not run brew cleanup postgresql until you have performed the migration.

    To have launchd start postgresql now and restart at login: brew services start postgresql Or, if you don't want/need a background service you can just run: pg_ctl -D /usr/local/var/postgres start

    You may wish to add the GOROOT-based install location to your PATH: export PATH=$PATH:/usr/local/opt/go/libexec/bin

  • [ ]

    Example configuration has been installed to: /usr/local/opt/tmux/share/tmux

    Bash completion has been installed to: /usr/local/etc/bash_completion.d

References and Resources

#!/usr/bin/env bash
# curl -sSL https://example.com/bootstrap.sh | bash -s -- -n name
set -eu
set -o nounset
set -o pipefail
# env
# ------------------------------------------------------------------------------
: ${BOOTSTRAP_GIST:="https://gist.githubusercontent.com/coreyti/c398f39af214ed61756006c042e7063d/raw"}
: ${HOMEBREW_PREFIX:="/usr/local"}
: ${BOOTSTRAP_RUBY:="2.4.0"}
# options
# ------------------------------------------------------------------------------
while getopts ':u:t:' opt ; do
case "${opt}" in
# n ) COMPUTER_NAME="${OPTARG}" ;;
u ) BOOTSTRAP_USER="${OPTARG}" ;;
t ) BOOTSTRAP_TEAM="${OPTARG}" ;;
\?) echo
echo "Option does not exist : ${OPTARG}"
exit 1
;;
esac
done
# usage
# ------------------------------------------------------------------------------
# TODO
# system
# ------------------------------------------------------------------------------
function system::hostname() {
local current=$(scutil --get ComputerName)
log::check "system::hostname; name: '${COMPUTER_NAME}'"
if [ "${current}" != "${COMPUTER_NAME}" ] ; then
log::bool 'yes'
sudo scutil --set ComputerName ${COMPUTER_NAME}
sudo scutil --set LocalHostName ${COMPUTER_NAME}
# systemsetup -setlocalsubnetname ${COMPUTER_NAME}
# systemsetup -setcomputername ${COMPUTER_NAME}
else
log::bool 'no'
fi
}
# home
# ------------------------------------------------------------------------------
function home::setup() {
log::check "home::setup - ~/bin"
if [ ! -d "${HOME}/bin/" ] ; then
log::bool 'yes'
mkdir "${HOME}/bin"
else
log::bool 'no'
fi
log::check "home::setup - ~/.bash_profile"
if [ ! -f "${HOME}/.bash_profile" ] ; then
log::bool 'yes'
touch "${HOME}/.bash_profile"
echo '' > "${HOME}/.bash_profile"
else
log::bool 'no'
fi
}
# brew
# ------------------------------------------------------------------------------
function brew::setup() {
local url='https://raw.githubusercontent.com/Homebrew/install/master/install'
log::check "brew::setup"
# make sure /usr/local exists and is mine.
if [ -d "${HOMEBREW_PREFIX}" ] ; then
if ! [ -r "${HOMEBREW_PREFIX}" ] ; then
sudo chown -R "${LOGNAME}:admin" ${HOMEBREW_PREFIX}
fi
else
sudo mkdir ${HOMEBREW_PREFIX}
sudo chflags norestricted ${HOMEBREW_PREFIX}
sudo chown -R "${LOGNAME}:admin" ${HOMEBREW_PREFIX}
fi
if ! type brew > /dev/null ; then
log::bool 'yes'
curl -fsSL ${url} | ruby
# TODO: move to a .bash_profile management function
printf '\nexport PATH="/usr/local/bin:$PATH"\n' >> ${HOME}/.bash_profile
export PATH="/usr/local/bin:$PATH"
else
log::bool 'no'
fi
}
function brew::bundle() {
local bust=$(date "+%s")
local url="${BOOTSTRAP_GIST}/Brewfile?dl=${bust}"
log::check "brew::bundle"
log::bool 'yes'
# log::info "downloading Brewfile from ${url}"
curl -fsSL ${url} > "${HOME}/.Brewfile"
brew update
brew bundle -v --global
util::bash_profile 'export PATH="$PATH:/usr/local/opt/go/libexec/bin"'
util::bash_profile 'export PATH="/usr/local/opt/sqlite/bin:$PATH"'
util::bash_profile '[ -f /usr/local/etc/bash_completion ] && . /usr/local/etc/bash_completion'
util::bash_profile '[ -f /usr/local/opt/chruby/share/chruby/chruby.sh ] && . /usr/local/opt/chruby/share/chruby/chruby.sh'
util::bash_profile '[ -f /usr/local/opt/chruby/share/chruby/auto.sh ] && . /usr/local/opt/chruby/share/chruby/auto.sh'
brew services start postgresql
# run `/usr/local/Caskroom/lastpass/latest/LastPass Installer.app`
}
# ruby
# ------------------------------------------------------------------------------
function ruby::install() {
local version="$1"
local openssl=${HOMEBREW_PREFIX}/opt/openssl
log::check "ruby::install; version: ${version}"
if [ ! -d "${HOME}/.rubies/ruby-${version}" ] ; then
log::bool 'yes'
ruby-install -L > /dev/null
ruby-install ruby ${version} -- --with-openssl-dir=${openssl}
else
log::bool 'no'
fi
}
function ruby::gemset() {
local version="$1"
set +o nounset
. /usr/local/opt/chruby/share/chruby/chruby.sh
chruby ${version}
set -o nounset
util::gemrc 'install: --no-document'
util::gemrc 'update: --no-document'
log::check "ruby::gemset; gem: --system"
if [ "$(gem list ^rubygems-update$ -lq)" == "$(gem list ^rubygems-update$ -rq)" ] ; then
log::bool 'no'
else
log::bool 'yes'
gem update --system
fi
log::check "ruby::gemset; gem: bundler"
if [ "$(gem list ^bundler$ -lq)" == "$(gem list ^bundler$ -rq)" ] ; then
log::bool 'no'
else
log::bool 'yes'
# update or install
if gem list ^bundler$ --installed > /dev/null; then
gem update bundler
else
gem install bundler
cores=$(sysctl -n hw.ncpu)
bundle config --global jobs $((cores - 1))
fi
fi
log::check "ruby::gemset; bundle install"
log::bool 'yes'
}
function ruby::bundle() {
local version="$1"
local bust=$(date "+%s")
local url="${BOOTSTRAP_GIST}/Gemfile?dl=${bust}"
log::check "ruby::bundle"
log::bool 'yes'
# log::info "downloading Gemfile from ${url}"
curl -fsSL ${url} > "${HOME}/.Gemfile"
set +o nounset
. /usr/local/opt/chruby/share/chruby/chruby.sh
chruby ${version}
set -o nounset
BUNDLER_GEMFILE="${HOME}/.Gemfile" bundle
}
# app
# ------------------------------------------------------------------------------
function app::atom() {
local bust=$(date "+%s")
local url="${BOOTSTRAP_GIST}/Atomfile?dl=${bust}"
log::check "app::atom"
log::bool 'yes'
curl -fsSL ${url} > "${HOME}/.Atomfile"
chmod +x "${HOME}/.Atomfile"
${HOME}/.Atomfile
}
# util
# ------------------------------------------------------------------------------
function util::bash_profile() {
local line="$1"
$(grep "${line}" ${HOME}/.bash_profile > /dev/null) \
|| echo "${line}" >> ${HOME}/.bash_profile
}
function util::gemrc() {
local line="$1"
$(grep "${line}" ${HOME}/.gemrc > /dev/null) \
|| echo "${line}" >> ${HOME}/.gemrc
}
# log
# ------------------------------------------------------------------------------
function log::info() {
local msg="$1"
printf "[bootstrap] $msg\n"
}
function log::check() {
local msg="$1"
# printf "[bootstrap] - [ ] $msg ... "
printf "[bootstrap] - [ ] %-50s ... " "$msg"
}
function log::bool() {
local msg="$1"
printf "$msg\n"
}
# pref
# ------------------------------------------------------------------------------
# NOTE: these do not appear to be persisted on refresh.
function pref::trackpad() {
log::check "pref::trackpad"
log::bool 'yes'
# Tap to click
defaults write com.apple.AppleMultitouchTrackpad Clicking -bool true
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
# defaults read com.apple.AppleMultitouchTrackpad
# defaults read com.apple.driver.AppleBluetoothMultitouch.trackpad
# ...
defaults write com.apple.AppleMultitouchTrackpad Dragging -bool true
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Dragging -bool true
# ...
defaults write com.apple.AppleMultitouchTrackpad TrackpadPinch -bool true
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadPinch -bool true
# Tap with two fingers to emulate right click
defaults write com.apple.AppleMultitouchTrackpad TrackpadRightClick -bool true
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRightClick -bool true
}
function pref::finder() {
log::check "pref::finder"
log::bool 'yes'
# Show hidden files
defaults write com.apple.finder AppleShowAllFiles -bool YES
# Hide all on the desktop
defaults write com.apple.finder CreateDesktop -bool false
# Avoid creating .DS_Store files on network volumes
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
# Use column view
defaults write com.apple.finder FXPreferredViewStyle -string "clmv"
}
function pref::screensaver() {
log::check "pref::screensaver"
log::bool 'no'
# Ask for password after 5 seconds
# defaults write com.apple.screensaver askForPassword -int 1
# defaults write com.apple.screensaver askForPasswordDelay -int 5
# Screen Saver: Flurry
# defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName -string "Flurry" path -string "/System/Library/Screen Savers/Flurry.saver" type -int 0
}
function pref::global() {
log::check "pref::global"
log::bool 'yes'
# Show file extensions
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
# Disable auto-correction
defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false
# Enable key repeat
# defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
# Set keyboard repeat rate
defaults write NSGlobalDomain InitialKeyRepeat -int 15
defaults write NSGlobalDomain KeyRepeat -int 2
# Tracking speeds
defaults write NSGlobalDomain com.apple.mouse.scaling -float 1.5
defaults write NSGlobalDomain com.apple.trackpad.scaling -float 1.5
# Don't restore windows when quitting or re-opening apps
defaults write NSGlobalDomain NSQuitAlwaysKeepsWindows -bool false
}
function pref::refresh() {
# killall "Finder" > /dev/null 2>&1
# killall "SystemUIServer" > /dev/null 2>&1
# killall "Dock" > /dev/null 2>&1
#
# apps=(
# "System Preferences"
# )
#
# for app in "${apps[@]}"
# do
# killall "${app}" > /dev/null 2>&1
# if [[ $? -eq 0 ]]; then
# # Re-open
# open -a "${app}"
# fi
# done
killall -u $(whoami) cfprefsd
}
# main
# ------------------------------------------------------------------------------
function main() {
# log::info "Running jobs for user, '$BOOTSTRAP_USER'"
# system::hostname
home::setup
brew::setup
brew::bundle
ruby::install ${BOOTSTRAP_RUBY}
ruby::gemset ${BOOTSTRAP_RUBY}
ruby::bundle ${BOOTSTRAP_RUBY}
pref::global
pref::finder
pref::trackpad
# broken...
# pref::refresh
app::atom
echo
# log::info "Running jobs for team, '$BOOTSTRAP_TEAM'"
}
sudo -v && main "$@"
# homebrew-bundle
# https://github.com/Homebrew/homebrew-bundle
# `brew bundle install --global`
tap "caskroom/cask"
tap "cloudfoundry/tap"
tap "git-duet/tap"
tap "homebrew/bundle"
tap "homebrew/core"
tap "homebrew/services"
tap "homebrew/versions"
# Homebrew
# https://github.com/Homebrew/brew/
brew "automake"
brew "libffi"
brew "libyaml"
brew "openssl"
brew "readline"
brew "bash-completion"
brew "bosh-cli"
brew "cf-cli"
brew "chruby"
brew "ctags"
brew "direnv"
brew "fswatch"
brew "git"
brew "git-duet"
brew "go"
brew "go-delve/delve/delve"
brew "htop"
brew "mas"
brew "node"
brew "pandoc"
brew "postgresql", service_restart: true
brew "python"
brew "ruby-install"
brew "sshuttle"
brew "sqlite"
brew "terraform"
brew "tmux"
brew "tree"
brew "vim"
brew "wget"
# homebrew-cask
# https://github.com/caskroom/homebrew-cask
cask "1clipboard"
# cask "1password" # EXCLUDE : passwords/trust
# cask "adobe-creative-cloud" # RELOCATE : user - coreyti (context: home)
# cask "airfoil" # RELOCATE : user - coreyti (context: home)
# cask "airserver" # RELOCATE : user - coreyti (context: home)
cask "atom"
cask "bartender"
cask "cheatsheet"
cask "docker-toolbox"
# cask "doxie" # RELOCATE : user - coreyti (context: home)
# cask "dropbox" # RELOCATE : user - coreyti (context: home)
cask "google-chrome"
cask "google-cloud-sdk"
cask "istat-menus"
cask "iterm2"
# cask "keybase" # RELOCATE : user - coreyti (context: home)
# cask "knox" # RELOCATE : user - coreyti (context: home)
# cask "lastpass" # EXCLUDE : passwords/trust
cask "lunchy"
cask "plistedit-pro"
# cask "prizmo" # RELOCATE : user - coreyti (context: home)
cask "screenhero"
cask "sizeup"
cask "slack"
cask "slate"
cask "teleport"
cask "tunnelblick"
cask "vagrant"
cask "xscope"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment