Install Home brew on Mac OS from Jamf Pro (Standard and Admin Users)

Kapil
New Contributor III

Hi All,

Hope this script help you all to install the home brew from JAMF for standard account users and admin account users. It also supports for BigSur OS.

#!/bin/sh
#
# Script Name: installHomebrew.sh
# Function: Deploy Homebrew (brew.sh) to the first user added to a new Mac during the post-DEP enrollment DEPNotify run
# Requirements: DEP, Jamf
#
# Copyright 2020, Route 1337, LLC, All Rights Reserved.
#
# Maintainers:
# - Matthew Ahrenstein: matthew@route1337.com
#
# Contributors:
# - "Dakr-xv": https://github.com/Dakr-xv
#
# See LICENSE
#

# Apple approved way to get the currently logged in user (Thanks to Froger from macadmins.org and https://developer.apple.com/library/content/qa/qa1133/_index.html)
ConsoleUser="$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')"

# Check to see if we have XCode already
checkForXcode=$( pkgutil --pkgs | grep com.apple.pkg.CLTools_Executables | wc -l | awk '{ print $1 }' )

# If XCode is missing we will install the Command Line tools only as that's all Homebrew needs
if [[ "$checkForXcode" != 1 ]]; then
  # Save current IFS state
  OLDIFS=$IFS
  IFS='.' read osvers_major osvers_minor osvers_dot_version <<< "$(/usr/bin/sw_vers -productVersion)"
  # restore IFS to previous state
  IFS=$OLDIFS
  cmd_line_tools_temp_file="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress"
  # Installing the latest Xcode command line tools on 10.9.x or higher
  if [[ ( ${osvers_major} -eq 10 && ${osvers_minor} -ge 9 ) || ( ${osvers_major} -eq 11 && ${osvers_minor} -ge 0 ) ]]; then
    # Create the placeholder file which is checked by the softwareupdate tool
    # before allowing the installation of the Xcode command line tools.
    touch "$cmd_line_tools_temp_file"
    # Identify the correct update in the Software Update feed with "Command Line Tools" in the name for the OS version in question.
    if [[ ( ${osvers_major} -eq 10 && ${osvers_minor} -ge 15 ) || ( ${osvers_major} -eq 11 && ${osvers_minor} -ge 0 ) ]]; then
       cmd_line_tools=$(softwareupdate -l | awk '/* Label: Command Line Tools/ { $1=$1;print }' | sed 's/^[[ 	]]*//;s/[[ 	]]*$//;s/*//' | cut -c 9-)
    elif [[ ( ${osvers_major} -eq 10 && ${osvers_minor} -gt 9 ) ]] && [[ ( ${osvers_major} -eq 10 && ${osvers_minor} -lt 15 ) ]]; then
       cmd_line_tools=$(softwareupdate -l | awk '/* Command Line Tools/ { $1=$1;print }' | grep "$macos_vers" | sed 's/^[[ 	]]*//;s/[[ 	]]*$//;s/*//' | cut -c 2-)
    elif [[ ( ${osvers_major} -eq 10 && ${osvers_minor} -eq 9 ) ]]; then
       cmd_line_tools=$(softwareupdate -l | awk '/* Command Line Tools/ { $1=$1;print }' | grep "Mavericks" | sed 's/^[[ 	]]*//;s/[[ 	]]*$//;s/*//' | cut -c 2-)
    fi
    # Check to see if the softwareupdate tool has returned more than one Xcode
    # command line tool installation option. If it has, use the last one listed
    # as that should be the latest Xcode command line tool installer.
    if (( $(grep -c . <<<"$cmd_line_tools") > 1 )); then
       cmd_line_tools_output="$cmd_line_tools"
       cmd_line_tools=$(printf "$cmd_line_tools_output" | tail -1)
    fi
    #Install the command line tools
    softwareupdate -i "$cmd_line_tools" --verbose
    # Remove the temp file
    if [[ -f "$cmd_line_tools_temp_file" ]]; then
      rm "$cmd_line_tools_temp_file"
    fi
  fi
fi

# Test if Homebrew is installed and install it if it is not
if test ! "$(sudo -u $ConsoleUser which brew)"; then
  # Jamf will have to execute all of the directory creation functions Homebrew normally does so we can bypass the need for sudo

  # Manually install the initial Homebrew
  /bin/mkdir -p /usr/local/Homebrew
  curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C /usr/local/Homebrew

  # Core directories
  /bin/mkdir -p /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/Caskroom
  /bin/mkdir -p /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/var/homebrew/linked
  /bin/mkdir -p /usr/local/share/zsh/site-functions /usr/local/var
  /bin/mkdir -p /usr/local/share/doc /usr/local/man/man1 /usr/local/share/man/man1
  /usr/sbin/chown -R $ConsoleUser:admin /usr/local/*
  /bin/chmod -Rf g+rwx /usr/local/*
  /bin/chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions

  # Cache directories
  mkdir -p /Library/Caches/Homebrew
  chmod g+rwx /Library/Caches/Homebrew
  chown $ConsoleUser:staff /Library/Caches/Homebrew

  # Create a system wide cache folder
  mkdir -p /Library/Caches/Homebrew
  chmod g+rwx /Library/Caches/Homebrew
  chown $ConsoleUser:staff /Library/Caches/Homebrew

  # Symlink Homebrew to the usual place
  ln -s /usr/local/Homebrew/bin/brew /usr/local/bin/brew

  # Run an initial update
  sudo -H -iu ${ConsoleUser} /usr/local/bin/brew update  </dev/null

  # Disable Homebrew analytics
  sudo -H -iu ${ConsoleUser} /usr/local/bin/brew analytics off  </dev/null

# If Homebrew is already installed then just echo that it is already installed
else
  echo "Homebrew is already installed"
fi
14 REPLIES 14

mickl089
Contributor III

I try it today, thanks a lot!

edit: tried.... made a policy for self service with this script. the install process is running and running....

bwoods
Valued Contributor

This is what I'm using. Can confirm that it still works. Don't forget to install Xcode command line tools first. In the script above I think that the command line tools are failing to install. This happens even when you try to install directly via terminal sometimes too. I would suggest packaging xcode cli first and install before running the script.

#!/bin/bash

# Script to install Homebrew on a Mac.
# Author: richard at richard - purves dot com
# Version: 1.0 - 21st May 2017

# Heavily hacked by Tony Williams (honestpuck@gmail.com)
# Latest version at https://github.com/Honestpuck/homebrew.sh
# v2.0 - 19th Sept 2019
# v2.0.1 Fixed global cache error
# v2.0.2 Fixed brew location error
# v2.0.3 Added more directories to handle

# v3.0 Catalina version 2020-02-17
# v3.1 | 2020-03-24 | Fix permissions for /private/tmp
# v3.2 2020-07-18 Added Caskroom to directories created and added check for binary
# update if it exists then exit

# Set up variables and functions here
consoleuser="$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')"

if [[ -e /usr/local/bin/brew ]]; then
    su -l "$consoleuser" -c "/usr/local/bin/brew update"
    exit 0
fi

# are we in the right group
check_grp=$(groups ${consoleuser} | grep -c '_developer')
if [[ $check_grp != 1 ]]; then
    /usr/sbin/dseditgroup -o edit -a "${consoleuser}" -t user _developer
fi

# Logging stuff starts here
LOGFOLDER="/private/var/log/"
LOG="${LOGFOLDER}Homebrew.log"

if [ ! -d "$LOGFOLDER" ]; then
    mkdir $LOGFOLDER
fi

function logme()
{
# Check to see if function has been called correctly
    if [ -z "$1" ] ; then
        echo "$(date) - logme function call error: no text passed to function! Please recheck code!"
        echo "$(date) - logme function call error: no text passed to function! Please recheck code!" >> $LOG
        exit 1
    fi

# Log the passed details
    echo -e "$(date) - $1" >> $LOG
    echo -e "$(date) - $1"
}

# Check and start logging
logme "Homebrew Installation"

# Have the xcode command line tools been installed?
logme "Checking for Xcode Command Line Tools installation"
check=$( pkgutil --pkgs | grep -c "CLTools_Executables" )

if [[ "$check" != 1 ]]; then
    logme "Installing Xcode Command Tools"
    # This temporary file prompts the 'softwareupdate' utility to list the Command Line Tools
    touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
    clt=$(softwareupdate -l | grep -B 1 -E "Command Line (Developer|Tools)" | awk -F"*" '/^ +\*/ {print $2}' | sed 's/^ *//' | tail -n1)
    # the above don't work in Catalina so ...
    if [[ -z $clt ]]; then
        clt=$(softwareupdate -l | grep  "Label: Command" | tail -1 | sed 's#* Label: (.*)#1#')
    fi
    softwareupdate -i "$clt"
    rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
    /usr/bin/xcode-select --switch /Library/Developer/CommandLineTools
fi

# Is homebrew already installed?
if [[ ! -e /usr/local/bin/brew ]]; then
    # Install Homebrew. This doesn't like being run as root so we must do this manually.
    logme "Installing Homebrew"

    mkdir -p /usr/local/Homebrew
    # Curl down the latest tarball and install to /usr/local
    curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C /usr/local/Homebrew

    # Manually make all the appropriate directories and set permissions
    mkdir -p /usr/local/Cellar /usr/local/Homebrew mkdir /usr/local/Caskroom /usr/local/Frameworks /usr/local/bin
    mkdir -p /usr/local/include /usr/local/lib /usr/local/opt /usr/local/etc /usr/local/sbin
    mkdir -p /usr/local/share/zsh/site-functions /usr/local/var
    mkdir -p /usr/local/share/doc /usr/local/man/man1 /usr/local/share/man/man1
    chown -R "${consoleuser}":_developer /usr/local/*
    chmod -R g+rwx /usr/local/*
    chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions

    # Create a system wide cache folder  
    mkdir -p /Library/Caches/Homebrew
    chmod g+rwx /Library/Caches/Homebrew
    chown "${consoleuser}:_developer" /Library/Caches/Homebrew

    # put brew where we can find it
    ln -s /usr/local/Homebrew/bin/brew /usr/local/bin/brew

    # Install the MD5 checker or the recipes will fail
    su -l "$consoleuser" -c "/usr/local/bin/brew install md5sha1sum"
    echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' | 
    tee -a /Users/${consoleuser}/.bash_profile /Users/${consoleuser}/.zshrc
    chown ${consoleuser} /Users/${consoleuser}/.bash_profile /Users/${consoleuser}/.zshrc

    # clean some directory stuff for Catalina
    chown -R root:wheel /private/tmp
    chmod 777 /private/tmp
    chmod +t /private/tmp
fi

# Make sure everything is up to date
logme "Updating Homebrew"
su -l "$consoleuser" -c "/usr/local/bin/brew update" 2>&1 | tee -a ${LOG}

# logme user that all is completed
logme "Installation complete"

exit 0

"packaging xcode cli first and install before running the script."

 

Do you mean making a .pkg in composer?  What folder do you need to drag into Composer to accomplish that?

I have a script that is used to install Xcode before the script to install Homebrew in the same policy... Terminal does confirm Xcode tools are installed but it does continue to hang running the Homebrew script.

 

bwoods
Valued Contributor

Just create a blank package with a postinstall script for XCode CLI or just make a preintall script for homebrew in your policy.

Can confirm this script is working well with Sanoma via Jamf pro

MikeBlock
New Contributor

@jlombardo How are you packaging Xcode? I'm having a tough time avoiding the prompt for admin creds when it installs. My end users can't install without providing those credentials.

@MikeBlock, rather than packaging XCode CLI Tools, I install it via bash script. It doesn't prompt the user for credentials, doesn't involve Composer, and can be used for multiple versions of MacOS without modification.

This is based on another XCode CLI installer someplace that I modified along the way and I'm sorry but I lost the original author, but I'm not sure how much of the original really remains at this point.

Works for MacOS 10.9 Mavericks and newer.

 

 

#!/bin/bash
### Use "ifneeded" as parameter 4 for non-automatically overwriting installs.
### Particularly for Homebrew or something that uses this as a dependency.
### If run with no argument, it will re-install the latest version.

if [[ "$4" == "true" ]]; then
	if ! xcode-select  -p 2>&1 | grep -q error; then
		echo "XCode CLI Tools already installed"
		exit 0
	fi
	echo "Needs XCode tools"
fi

echo "Installing xcode tools"
# Installing the Xcode command line tools on 10.7.x or higher
osx_major=$(sw_vers -productVersion | awk -F "." '{print $1}')
osx_vers=$(sw_vers -productVersion | awk -F "." '{print $2}')
cmd_line_tools_temp_file="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress"

# If OSX Version is 11.0 or higher, translate that into 10.16 or higher
if [[ "$osx_major" -gt 10 ]]; then
	(( osx_vers=osx_major+5 )) || true
fi

## Installing the latest Xcode command line tools on 10.9.x or higher
# Create the placeholder file which is checked by the softwareupdate tool
# before allowing the installation of the Xcode command line tools.
touch "$cmd_line_tools_temp_file"

# Identify the correct update in the Software Update feed with "Command Line Tools" in the name for the OS version in question.
if [[ "$osx_vers" -gt 9 ]]; then
	cmd_line_tools=$(softwareupdate -l | grep -E '\*.*Command Line Tools.*' | sed 's/\*.*\(Command Line Tools.*\)$/\1/' | sed -e 's/^[ \t]*//' )
elif [[ "$osx_vers" -eq 9 ]]; then
	cmd_line_tools=$(softwareupdate -l | awk '/\*\ Command Line Tools/ { $1=$1;print }' | grep "Mavericks" | sed 's/^[[ \t]]*//;s/[[ \t]]*$//;s/*//' | cut -c 2-)
fi

# Check to see if the softwareupdate tool has returned more than one Xcode
# command line tool installation option. If it has, use the last one listed
# as that should be the latest Xcode command line tool installer.
if (( $(grep -c . <<<"$cmd_line_tools") > 1 )); then
	cmd_line_tools_output="$cmd_line_tools"
	cmd_line_tools=$(printf "$cmd_line_tools_output" | tail -1)
fi

#Install the command line tools
softwareupdate -i "$cmd_line_tools" --verbose

# Remove the temp file
rm -f "$cmd_line_tools_temp_file"

 

 

not sure if this is working on Ventura? I can get a response still to the check script on a Monterey box, but only get "No new software available." on a Ventura box.

I'm extracting out the actual command for testing, not running the entire script: 

softwareupdate -l | grep -E '\*.*Command Line Tools.*' | sed 's/\*.*\(Command Line Tools.*\)$/\1/' | sed -e 's/^[ \t]*//'

 

Working perfectly on Ventura 13.6. How nice to see CL Tools install, with no GUI pop ups....

It's been awhile since I posted that XCode CLI Tools installer, and I've made some minor changes over the years, so I wanted to include my current version in the event anyone finds this useful :-)

Currently being used successfully on 14.2+

#!/bin/bash
### Use "true" as parameter 4 for non-automatically overwriting installs.
### Particularly for Homebrew or something that uses this as a dependency.
### If run with no argument, it will re-install the latest version.

if [[ "$4" == "true" ]]; then
	if ! xcode-select  -p 2>&1 | grep -q error; then
		echo "XCode CLI Tools already installed"
		exit 0
	fi
	echo "Needs XCode tools"
fi

echo "Installing xcode tools"
# Installing the Xcode command line tools on 10.7.x or higher
osx_major_ver=$(/usr/bin/sw_vers -productVersion | /usr/bin/awk -F. '{print $1}')
osx_minor_ver=$(/usr/bin/sw_vers -productVersion | /usr/bin/awk -F. '{print $2}')
cmd_line_tools_temp_file="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress"

## Installing the latest Xcode command line tools on 10.9.x or higher
# Create the placeholder file which is checked by the softwareupdate tool
# before allowing the installation of the Xcode command line tools.
touch "$cmd_line_tools_temp_file"

# Identify the correct update in the Software Update feed with "Command Line Tools" in the name for the OS version in question.
if [[ "$osx_major_ver" -lt 10 ]] || [[ "$osx_major_ver" -eq 10 ]] && [[ "$osx_minor_ver" -lt 9 ]]; then
	echo "Unsupported MacOS Version: ${osx_major_ver}.${osx_minor_ver}"
	exit 1
elif [[ "$osx_major_ver" -eq 10 ]] && [[ "$osx_minor_ver" -eq 9 ]]; then
	cmd_line_tools=$(softwareupdate -l | awk '/\*\ Command Line Tools/ { $1=$1;print }' | grep "Mavericks" | sed 's/^[[ \t]]*//;s/[[ \t]]*$//;s/*//' | cut -c 2-)
elif [[ "$osx_major_ver" -eq 10 ]] && [[ "$osx_minor_ver" -gt 9 ]] && [[ "$osx_minor_ver" -lt 15 ]]; then
	cmd_line_tools=$(/usr/sbin/softwareupdate --list 2>&1 | /usr/bin/awk -F"[*] " '/\* Command Line Tools/ {print $NF}' | \
    /usr/bin/sed 's/^ *//' | /usr/bin/tail -1)
else
	cmd_line_tools=$(/usr/sbin/softwareupdate --list 2>&1 | /usr/bin/awk -F: '/Label: Command Line Tools for Xcode/ {print $NF}' | \
	/usr/bin/sed 's/^ *//' | /usr/bin/tail -1)
fi

# Check to see if the softwareupdate tool has returned more than one Xcode
# command line tool installation option. If it has, use the last one listed
# as that should be the latest Xcode command line tool installer.
if (( $(grep -c . <<<"$cmd_line_tools") > 1 )); then
	cmd_line_tools_output="$cmd_line_tools"
	cmd_line_tools=$(printf "$cmd_line_tools_output" | tail -1)
fi

#Install the command line tools
softwareupdate -i "$cmd_line_tools" --verbose

# Remove the temp file
rm -f "$cmd_line_tools_temp_file"

devoted_lkrygsm
New Contributor III

I've tried a script similar to this and it's great for just installing homebrew, but if you need to install homebrew plus a number of packages, the runtime on it will kill you. 😞 I've given up at this point and resigned myself to capturing homebrew and the standard packages we need to deploy with Composer and then using a small script to `chown -R` the homebrew folders to the current user.

I had one test machine take literally hours to install `homebrew` `gnupg2` and `pinentry-mac` to enable yubikey-based SSHing to our development servers, and that's just not gonna fly 🙂

Composer it is for me, but awesome that you have this!

Can you share your composer setup for brew.sh?

macguitarman
New Contributor III

I am pretty sure this is outdated, as homebrew is going to install in /opt/homebrew (for Apple chips)....Also, python is not installed by default, can use scutil...to ascertain logged in user (console user).

greenapple
New Contributor

This script does not work and gives function dquote