Deploy homebrew

dmarcnw
New Contributor III

I'm looking for advice on getting homebrew on new employee machines automatically. We have a work flow we would like to keep to as few clicks as possible.

I am trying to get the process of pulling down XCode CLI, installing homebrew, adding cask, and then installing third party apps for new employee machines.

I have the XCode CLI component down but having problems with installing homebrew and adding cask. Curious if anyone has a working script to make this happen. I am deploying this process through self service.

1 ACCEPTED SOLUTION

jhbush
Valued Contributor II

This may be of some help to you.

#!/bin/bash

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

# Set up variables and functions here
consoleuser="$(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 + "
");')"
brandid="com.application.id"
tn="/path/to/terminal-notifier.app/Contents/MacOS/terminal-notifier"
cd="/path/to/cocoaDialog.app/Contents/MacOS/cocoaDialog"

# 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"
}

function notify()
{
    su -l "$consoleuser" -c " "'"'$tn'"'" -sender "'"'$brandid'"'" -title "'"'$title'"'" -message "'"'$1'"'" "
    logme "$1"
}

# Check and start logging - done twice for local log and for JAMF
logme "Homebrew Installation"

# Let's start here by caffinating the mac so it stays awake or bad things happen.
caffeinate -d -i -m -u &
caffeinatepid=$!
logme "Caffinating the mac under process id: $caffeinatepid"

# Have the xcode command line tools been installed?
notify "Checking for Xcode Command Line Tools installation"
check=$( pkgutil --pkgs | grep com.apple.pkg.CLTools_Executables | wc -l | awk '{ print $1 }' )

if [[ "$check" != 1 ]];
then
    notify "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)
    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?
which -s brew
if [[ $? = 1 ]];
then
    # Install Homebrew. This doesn't like being run as root so we must do this manually.
    notify "Installing 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

    # Manually make all the appropriate directories and set permissions
    mkdir -p /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var
    chown -R $consoleuser /usr/local
    chmod g+rwx /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var
    chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions
    chgrp admin /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var

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

    # Install the MD5 checker or the recipes will fail
    su -l "$consoleuser" -c "/usr/local/bin/brew install md5sha1sum"
    su -l "$consoleuser" -c "echo "'"export PATH=/usr/local/opt/openssl/bin:$PATH"'" >> ~/.bash_profile"

    # Remove temporary folder
    rm -rf /usr/local/Homebrew
else
    # Run an update and quit
    notify "Updating Homebrew"
    su -l "$consoleuser" -c "/usr/local/bin/brew update" 2>&1 | tee -a ${LOG}
    exit 0
fi

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

# Notify user that all is completed
notify "Installation complete"

# No more caffeine please. I've a headache.
kill "$caffeinatepid"

exit 0

View solution in original post

61 REPLIES 61

jhbush
Valued Contributor II

This may be of some help to you.

#!/bin/bash

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

# Set up variables and functions here
consoleuser="$(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 + "
");')"
brandid="com.application.id"
tn="/path/to/terminal-notifier.app/Contents/MacOS/terminal-notifier"
cd="/path/to/cocoaDialog.app/Contents/MacOS/cocoaDialog"

# 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"
}

function notify()
{
    su -l "$consoleuser" -c " "'"'$tn'"'" -sender "'"'$brandid'"'" -title "'"'$title'"'" -message "'"'$1'"'" "
    logme "$1"
}

# Check and start logging - done twice for local log and for JAMF
logme "Homebrew Installation"

# Let's start here by caffinating the mac so it stays awake or bad things happen.
caffeinate -d -i -m -u &
caffeinatepid=$!
logme "Caffinating the mac under process id: $caffeinatepid"

# Have the xcode command line tools been installed?
notify "Checking for Xcode Command Line Tools installation"
check=$( pkgutil --pkgs | grep com.apple.pkg.CLTools_Executables | wc -l | awk '{ print $1 }' )

if [[ "$check" != 1 ]];
then
    notify "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)
    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?
which -s brew
if [[ $? = 1 ]];
then
    # Install Homebrew. This doesn't like being run as root so we must do this manually.
    notify "Installing 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

    # Manually make all the appropriate directories and set permissions
    mkdir -p /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var
    chown -R $consoleuser /usr/local
    chmod g+rwx /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var
    chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions
    chgrp admin /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var

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

    # Install the MD5 checker or the recipes will fail
    su -l "$consoleuser" -c "/usr/local/bin/brew install md5sha1sum"
    su -l "$consoleuser" -c "echo "'"export PATH=/usr/local/opt/openssl/bin:$PATH"'" >> ~/.bash_profile"

    # Remove temporary folder
    rm -rf /usr/local/Homebrew
else
    # Run an update and quit
    notify "Updating Homebrew"
    su -l "$consoleuser" -c "/usr/local/bin/brew update" 2>&1 | tee -a ${LOG}
    exit 0
fi

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

# Notify user that all is completed
notify "Installation complete"

# No more caffeine please. I've a headache.
kill "$caffeinatepid"

exit 0

View solution in original post

jwojda
Valued Contributor II

@jhbush1973 thank you! I had been looking for something like this a little while ago and couldn't find anything.

I just modified it to remove the caffinate and terminal notifier stuff and was able to install brew successfully via the script.

jhbush
Valued Contributor II

@jwojda just sharing the work of @franton I don't think this one is on his GitHub

jlang_remedy
New Contributor III

Dropped this script in our JSS and this is the output that I got.

Executing Policy Install Homebrew - JAMFNation
Running script Install Homebrew - JAMFNation...
Script exit code: 0
Script result: Tue Aug 8 12:08:02 EDT 2017 - Homebrew Installation
Tue Aug 8 12:08:02 EDT 2017 - Caffinating the mac under process id: 4998
for: -c: line 0: unexpected EOF while looking for matching `"'
for: -c: line 1: syntax error: unexpected end of file
Tue Aug 8 12:08:02 EDT 2017 - Checking for Xcode Command Line Tools installation
Homebrew" : -c: line 0: unexpected EOF while looking for matching `"'
Homebrew" : -c: line 1: syntax error: unexpected end of file
Tue Aug 8 12:08:02 EDT 2017 - Installing Homebrew
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed

0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 128 0 128 0 0 700 0 --:--:-- --:--:-- --:--:-- 703

82 1067k 82 878k 0 0 1332k 0 --:--:-- --:--:-- --:--:-- 1332k
100 1067k 100 1067k 0 0 1407k 0 --:--:-- --:--:-- --:--:-- 1922k
Updating Homebrew...
==> Homebrew has enabled anonymous aggregate user behaviour analytics.
Read the analytics documentation (and how to opt-out) here:
https://docs.brew.sh/Analytics.html

==> Tapping homebrew/core
Cloning into '/usr/local/Library/Taps/homebrew/homebrew-core'...
Tapped 4290 formulae (4,547 files, 11.2MB)
Error: /usr/local/Homebrew already exists.
Please remove it manually or uninstall and reinstall Homebrew into a new
location as the migration cannot be done automatically.
==> Cleaning up /Library/Caches/Homebrew...
==> Migrating /Library/Caches/Homebrew to /Users/adeveloper/Library/Caches/Homebrew...
==> Deleting /Library/Caches/Homebrew...
==> Migrating HOMEBREW_REPOSITORY (please wait)...
Warning: md5sha1sum 0.9.5 is already installed
Homebrew" : -c: line 0: unexpected EOF while looking for matching `"'
Homebrew" : -c: line 1: syntax error: unexpected end of file
Tue Aug 8 12:08:23 EDT 2017 - Updating Homebrew
Initialized empty Git repository in /usr/local/.git/
From https://github.com/Homebrew/brew
* [new branch] master -> origin/master
HEAD is now at 93051b2 formula_cellar_checks: fix broken dylib spacing.
==> Homebrew has enabled anonymous aggregate user behaviour analytics.
Read the analytics documentation (and how to opt-out) here:
https://docs.brew.sh/Analytics.html

Already up-to-date.
==> Migrating HOMEBREW_REPOSITORY (please wait)...
==> Migrated HOMEBREW_REPOSITORY to /usr/local/Homebrew!
Homebrew no longer needs to have ownership of /usr/local. If you wish you can
return /usr/local to its default ownership with:
sudo chown root:wheel /usr/local
complete" : -c: line 0: unexpected EOF while looking for matching `"'
complete" : -c: line 1: syntax error: unexpected end of file
Tue Aug 8 12:08:43 EDT 2017 - Installation complete

When trying to run a brew command from terminal on the machine (non-admin standard user) i'm getting 'brew' command not found. Any ideas on the errors above in the script, and why brew commands won't work even though all the folders were created and permissions seem right?

djdavetrouble
Contributor III

probably not in the path:
link text
either add to path or specify full path in terminal / scripts

jlang_remedy
New Contributor III

Since i'd rather change the script, what specifically would need editing in the script code above? It looks like full paths are laid out there.

@franton Any ideas here regarding your script and how it operates in the JSS?

franton
Valued Contributor II

@jlang_remedy Ok you run this as a self service policy. The only variables that should need changes are at the top of the script.

emily
Valued Contributor III

We threw this in Self Service:

#!/bin/bash

osascript <<'EOF'
tell application "Terminal"
    activate
    do script ("/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"") in window 1
end tell
EOF

exit 0

jlang_remedy
New Contributor III

@franton I threw the script in self-service and it seemed to install successfully, even despite some error statements in the log.

Eg. : -c: line 0: unexpected EOF while looking for matching `"'<br/>complete" : -c: line 1: syntax error: unexpected end of file<br/>Fri Aug 25 13:29:48 EDT 2017 - Installation complete<br/>

I opened terminal and tried some brew commands and still getting "-bash: brew: command not found". errors.

By the way, my use case is that an non-administrator local account is performing the self-service install and is the account that will be using brew. Does this script not work for that scenario?

franton
Valued Contributor II

@jlang_remedy And yet my local copy works from Self Service ok.

#!/bin/bash

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

# Set up variables and functions here
export consoleuser="$(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 + "
");')"
export brandid="com.company.id"
export tn="/usr/local/cs/bin/terminal-notifier"
export cd="/usr/local/cs/bin/cocoaDialog.app/Contents/MacOS/cocoaDialog"
export title="Homebrew Installation"

# Logging stuff starts here
export LOGFOLDER="/private/var/log/"
export 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"
}

function notify()
{
    OIFS=$IFS
    IFS=$'
'
    su -l "$consoleuser" -c " "'"'$tn'"'" -sender "'"'$brandid'"'" -title "'"'$title'"'" -message "'"'$1'"'" "
    logme "$1"
    IFS=$OIFS
}

# Check and start logging - done twice for local log and for JAMF
logme "Homebrew Installation"

# Let's start here by caffinating the mac so it stays awake or bad things happen.
caffeinate -d -i -m -u &
caffeinatepid=$!
logme "Caffinating the mac under process id: $caffeinatepid"

# Have the xcode command line tools been installed?
notify "Checking for Xcode Command Line Tools installation"
check=$( pkgutil --pkgs | grep com.apple.pkg.CLTools_Executables | wc -l | awk '{ print $1 }' )

if [[ "$check" != 1 ]];
then
    notify "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)
    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?
which -s brew
if [[ $? = 1 ]];
then
    # Install Homebrew. This doesn't like being run as root so we must do this manually.
    notify "Downloading 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 2>&1 | tee -a ${LOG}

    # Manually make all the appropriate directories and set permissions
    mkdir -p /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var
    chown -R $consoleuser /usr/local
    chmod g+rwx /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var
    chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions
    chgrp admin /usr/local/Cellar /usr/local/Homebrew /usr/local/Frameworks /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/opt /usr/local/sbin /usr/local/share /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var

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

    # Remove temporary folder
    rm -rf /usr/local/Homebrew

    # Install the MD5 checker or the recipes will fail
    notify "Installing md5sha1sum"
    su -l "$consoleuser" -c "/usr/local/bin/brew install md5sha1sum" 2>&1 | tee -a ${LOG}
    su -l "$consoleuser" -c "echo 'export PATH=/usr/local/opt/openssl/bin:$PATH' >> /Users/$consoleuser/.bash_profile"
else
    # Run an update and quit
    notify "Updating Homebrew"
    su -l "$consoleuser" -c "/usr/local/bin/brew update" 2>&1 | tee -a ${LOG}
    exit 0
fi

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

# Notify user that all is completed
notify "Installation complete"

# No more caffeine please. I've a headache.
kill "$caffeinatepid"

exit 0

I have no explanation for your errors. Above is what I'm using for Self Service install on non-admin accounts and it works.

jlang_remedy
New Contributor III

@franton Thanks for this version! It's working now for me in self-service. Looks like a few differences in this version, especially exporting variables. Thanks!

jamesreynolds
New Contributor III

This script is not safe if your users aren't admin and you don't want them to be admin. It changes the ownership of /usr/local and everything in it to the user that is logged in, which may not be admin. If nothing is installed there before this script runs it isn't a problem, but if you've got scripts already installed there then this will script will have some unintended consequences...

Echterling
New Contributor II

My question is, I am building a workflow to install 32 new macs for a lab situation and i want the install of brew to be in the initial workflow. There will be no self service on these machines. So will this script work using Jamf Imaging?

franton
Valued Contributor II

My own script is designed for self service only.

paulkenworthy
New Contributor

I've been trying to use the script posted by @franton however run into problems relating to High Sierra. In High Sierra I can't chown /usr/local anymore. The suggested fix I've been able to find is instead chown $(brew --prefix)/* So the only change made to the script is replacing:

chown -R $consoleuser /usr/local
with
chown -R $consoleuser $(brew --prefix)/*

running the script from self-service of a non-admin user, the following error is producing during the install:

Error: /usr/local is not writable

but the install appears to complete. Running brew doctor or brew update produces the same error however. This happens with a fresh install of the OS and homebrew. If anyone's had success getting homebrew installed via self-service in High Sierra I'd be very interested in how you've done it (the only info I've been able to find from the homebrew side is the changed chown command and the suggestion of re-installing homebrew).

isterling_goaaa
New Contributor III

@paulkenworthy Were you able to find a solution? I've found this post on Medium, but haven't had a chance to try it out yet. I think it'd be silly to use this solution though, since you'd essentially be installing brew twice.

paulkenworthy
New Contributor

@isterling.goaaa I'm afraid I wasn't.

I've tried uninstalling and reinstalling homebrew as per that link, however if I run the commands exactly as given on that page via JSS it fails, as installing Homebrew as root is dangerous. If I modify the uninstall and reinstall commands to match the installing command given earlier in this thread than the same /usr/local/ is not writable error is given.

gregreznik
New Contributor III

Hi all, here is what I'm using to install xcode, homebrew, and apps:

#!/bin/bash
# redirect stdout/stderr to a file
exec &> /var/log/HomeBrew.log

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 + "
");')

su -l "$consoleuser" -c "defaults read /Users/$consoleuser/Library/Preferences/com.apple.dock | grep corner"

echo -ne '
'  | sudo -u "$consoleuser" /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

sudo -u $consoleuser /usr/local/bin/brew cask
sudo -u $consoleuser /usr/local/bin/brew install caskroom/versions/sequel-pro-nightly
sudo -u $consoleuser /usr/local/bin/brew install caskroom/cask/iterm2
sudo -u $consoleuser /usr/local/bin/brew install caskroom/cask/intellij-idea
sudo -u $consoleuser /usr/local/bin/brew install caskroom/cask/charles
sudo -u $consoleuser /usr/local/bin/brew install caskroom/versions/sublime-text-dev
sudo -u $consoleuser /usr/local/bin/brew install caskroom/cask/sourcetree
sudo -u $consoleuser /usr/local/bin/brew install node
sudo -u $consoleuser /usr/local/bin/brew install python3
sudo -u $consoleuser /usr/local/bin/brew install nginx
sudo -u $consoleuser /usr/local/bin/brew install docker
sudo -u $consoleuser /usr/local/bin/brew install caskroom/cask/firefox

here is what happens next:

==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew
==> The following existing directories will be made group writable:
/usr/local/bin
==> The following existing directories will have their owner set to testtester:
/usr/local/bin
==> The following existing directories will have their group set to admin:
/usr/local/bin
==> The following new directories will be created:
/usr/local/Cellar
/usr/local/Homebrew
/usr/local/Frameworks
/usr/local/etc
/usr/local/include
/usr/local/lib
/usr/local/opt
/usr/local/sbin
/usr/local/share
/usr/local/share/zsh
/usr/local/share/zsh/site-functions
/usr/local/var
==> The Xcode Command Line Tools will be installed.
==> /usr/bin/sudo /bin/chmod u+rwx /usr/local/bin
sudo: no tty present and no askpass program specified
Failed during: /usr/bin/sudo /bin/chmod u+rwx /usr/local/bin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin
sudo: unknown user: /usr/local/bin/brew
sudo: unable to initialize policy plugin

Where it goes wrong:

sudo: no tty present and no askpass program specified 
Failed during: /usr/bin/sudo /bin/chmod u+rwx /usr/local/bin

Any thoughts on this? NOTE: this works through executing a terminal command via policy trigger, however, on initial enrollment we have setup with splashbuddy, it constantly gives us this error.

Danko
New Contributor III

Does maybe anyone having a solution on installing homebrew on High Sierra?

The ideal solution for us would be to install homebrew at the deployment process and provide application installers through self service to our non-admin user with the following example: „brew cask install cyberduck“.

Thank you in advance.

kevinwilemon
New Contributor III

@Danko - I've had a terrible time trying to install homebrew without interaction and unattended. Eventually we switched over to this which I modified from @emily 's post above and it's been the most consistent experience for us. It also doesn't require the user to run manually and doesn't run as root (which is preferred for Homebrew installs) so if your techs aren't onboarding, this is safe to run as a pre-stage for users as a policy in Self Service.

We have other applications that install via brew during deployment so they would also run those commands in this script which is why Homebrew has a pause while Window 1 of Terminal is active so they don't overlap each other. I removed those from below as you'll do that via Self Service.

#!/bin/bash

# Running caffeinate command so system doesn't bork the Homebrew install
caffeinate -d -i -m -u &
caffeinatepid=$!
echo "Caffeinating the mac under process id: $caffeinatepid"

# Open non-admin safe Terminal window, install Homebrew and wait until process is complete before continuing
osascript -e 'tell application "Terminal" to quit'
osascript <<'EOF'
tell application "Terminal"
    activate
    do script ("/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"") in window 1
    repeat
            delay 0.5
            if not busy of window 1 then exit repeat
        end repeat
end tell
EOF

# Insert additional brew installs here

# Ending caffeinate command
kill "$caffeinatepid"

# Close Terminal window
osascript -e 'tell application "Terminal" to quit'

exit 0

Danko
New Contributor III

@kevinwilemon - Thank you for the quick response.
How do you run this script? Policy? Self Service?

I've tried both way, but got stuck when the user have to press enter to continue the installation process.

Our idea would be to run the initial setup of Homebrew inside our deployment process as a policy (as localadmin).
After Homebrew is correctly installed we would like to provide Applications in the Self Service which just run a "brew cask install" command in the background to get the Apps installed.

kevinwilemon
New Contributor III

We run via Self Service (though it can be run as a policy as well). As I mentioned, we've had a terrible time trying to install Homebrew successfully when attempting to skip the interactive step and switched to this method for onboarding which then allows the user to install via brew whether they're an admin or not.

michaelherrick
New Contributor III

@kevinwilemon When I ran this script as a Self-Service item while logged in as a standard user, I got an error that I must be an administrator to install

ctw
New Contributor III

@kevinwilemon I was able to install homebrew as a standard user, but how are you deploying applications after it has been installed? I'm getting errors about user not being in sudoers file or not being able to move the .app from their home directory to /Applications .

sdamiano
Contributor

I am having a difficult time getting this to work in in Mojave.

The script highlighted as the solution here keeps giving errors on the /usr/local folder. I have noticed that the script, written as is, and brought in to Jamf Pro's script section, and deployed to a new machine, does not execute any of the tasks beneath "# Manually make all the appropriate directories and set permissions"

Anyone have any ideas? I have tried writing those lines to execute as su -l "$consoleuser" -c, i've tried packaging it as a separate script and running it under files and processes, and I'm running in to every dead end.

mwolf423
New Contributor II

@sdamiano Unfortunately, with /usr falling under SIP, the script will not work. After found out it broke, we started using @emily 's method since our developers are local admins.

It lets us script out the deployment of xcode cli tools, homebrew, jetbrains apps, and docker with 1 click and 1 password.

richies113
New Contributor II

Hi @emily .

Have you tried your code on Mojave?

Thank you in advance.

jwojda
Valued Contributor II

@richies113 I've tested it on a couple 10.14 machines and it's worked fine (Thanks @emily )

seanism
New Contributor III

Ya 10.14 makes this difficult. Has anyone gotten homebrew to install automatically after enrollment?

gregreznik
New Contributor III

Hi everyone, here is a script that works on Mojave - I have implemented into our workflow at work, so its production-ready.

This will pull the latest CLI and install homebrew!

All credit goes to route 1337 - link to his github

#!/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 SplashBuddy run
# Requirements: DEP, SplashBuddy
#
# Copyright 2018, 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
    osx_vers=$(sw_vers -productVersion | awk -F "." '{print $2}')
    # This temporary file prompts the 'softwareupdate' utility to list the Command Line Tools
    touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
    # Verify softwareupdate installs only the latest XCode (Original code from https://github.com/rtrouton/rtrouton_scripts)
    cmd_line_tools=$(softwareupdate -l | awk '/* Command Line Tools/ { $1=$1;print }' | grep "$osx_vers" | sed 's/^[[ 	]]*//;s/[[ 	]]*$//;s/*//' | cut -c 2-)
    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
    softwareupdate -i "$cmd_line_tools"
    rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
    /usr/bin/xcode-select --switch /Library/Developer/CommandLineTools
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
  /bin/chmod u+rwx /usr/local/bin
  /bin/chmod g+rwx /usr/local/bin
  /bin/mkdir -p /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
  /bin/chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions
  /bin/chmod g+rwx /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
  /bin/chmod 755 /usr/local/share/zsh /usr/local/share/zsh/site-functions
  /usr/sbin/chown $ConsoleUser /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
  /usr/bin/chgrp admin /usr/local/bin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
  /bin/mkdir -p /Users/$ConsoleUser/Library/Caches/Homebrew
  /bin/chmod g+rwx /Users/$ConsoleUser/Library/Caches/Homebrew
  /usr/sbin/chown $ConsoleUser /Users/$ConsoleUser/Library/Caches/Homebrew
  /bin/mkdir -p /Library/Caches/Homebrew
  /bin/chmod g+rwx /Library/Caches/Homebrew
  /usr/sbin/chown $ConsoleUser /Library/Caches/Homebrew


  # Install Homebrew as the currently logged in user
  sudo -H -u $ConsoleUser ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"  </dev/null
# If Homebrew is already installed then just echo that it is already installed
else
  echo "Homebrew is already installed"
fi

This is ready to use with DEP and any onboarding splash screen app you use, such as Splashbuddy. Also, does work as a Self Service policy!

Enjoy!

lxfl
New Contributor II

hi,

@igreznik 's script worked well.
If your users are non-admins, you have to make them temporary admins to be able to install things or else you will get the following error:

Downloading Command Line Tools (macOS Mojave version 10.14) for Xcode Downloaded Command Line Tools (macOS Mojave version 10.14) for Xcode Installing Command Line Tools (macOS Mojave version 10.14) for Xcode Done with Command Line Tools (macOS Mojave version 10.14) for Xcode Done. This script requires the user yourusernamehere to be an Administrator. Error running script: return code was 1.

Add user to admingroup

sudo dseditgroup -o edit -a $ConsoleUser -t user admin

Remove him afterwards

sudo dseditgroup -o edit -d $ConsoleUser -t user admin

Not the beautiful way to do it, but nobody will notice... 🙂

michaelherrick
New Contributor III

I've been running @igreznik script , with the "add/remove local user to admin group" fix and it has been working well, but recently I get the following error on execution:

Script result: ==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew
==> The following existing directories will be made group writable:
/usr/local/lib/pkgconfig
==> The following existing directories will have their owner set to neilpalmer:
/usr/local/lib/pkgconfig
==> The following existing directories will have their group set to admin:
/usr/local/lib/pkgconfig
==> /usr/bin/sudo /bin/chmod u+rwx /usr/local/lib/pkgconfig

WARNING: Improper use of the sudo command could lead to data loss
or the deletion of important system files. Please double-check your
typing when using sudo. Type "man sudo" for more information.

To proceed, enter your password, or type Ctrl-C to abort.

sudo: no tty present and no askpass program specified
Failed during: /usr/bin/sudo /bin/chmod u+rwx /usr/local/lib/pkgconfig

Is it possible that something changed in the Homebrew ruby script on github?

troyewebster
New Contributor III

@michaelherrick I am running into the same thing ... anyone crack this nut?

dash4385
New Contributor II

This has been working great for me and Is updated to work the Catalina. The only drawback I have run into is because it is not using the ruby install it doesn't set path variables. But for what I use it for doesn't matter

#!/bin/sh

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 + "
");')"
tempAdminStatus=false


#Check to See if user is an admin or not. Makes the a temporary admin and set tempAdminStatus for removal later
if groups $ConsoleUser | grep -q -w admin;
then
    echo "User is an admin"
else
    echo "User is not an admin"
    echo "Setting as temp admin"
    tempAdminStatus=true
    dscl . -append /Groups/admin GroupMembership $ConsoleUser
fi


# If XCode is missing we will install the Command Line tools only as that's all Homebrew needs
# Check to see if we have XCode already
# Installing the Xcode command line tools on 10.7.x or higher (Original code from https://github.com/rtrouton/rtrouton_scripts)

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
    echo "Command Line tools are not installed. Will attempt to install."
    macos_vers=$(sw_vers -productVersion | 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

    if [[ "$macos_vers" -ge 9 ]]; 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 [[ "$macos_vers" -ge 15 ]]; then
        cmd_line_tools=$(softwareupdate -l | awk '/* Label: Command Line Tools/ { $1=$1;print }' | sed 's/^[[ 	]]*//;s/[[ 	]]*$//;s/*//' | cut -c 9-)   
      elif [[ "$macos_vers" -gt 9 ]] && [[ "$macos_vers" -le 14 ]]; then
        cmd_line_tools=$(softwareupdate -l | awk '/* Command Line Tools/ { $1=$1;print }' | grep "$macos_vers" | sed 's/^[[ 	]]*//;s/[[ 	]]*$//;s/*//' | cut -c 2-)
      elif [[ "$macos_vers" -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
    xcode-select -s /Library/Developer/CommandLineTools   
else
  echo "Command Lines Tools are already installed"
fi


# Test if Homebrew is installed and install it if it is not
if test ! -f /usr/local/Homebrew/bin/brew ; then
  # Jamf will have to execute all of the directory creation functions Homebrew normally does so we can bypass the need for sudo
  echo "Creating folder structure for brew and setting correct permissions."
  /bin/chmod u+rwx /usr/local/bin
  /bin/chmod g+rwx /usr/local/bin
  /bin/mkdir -p /usr/local/Homebrew /usr/local/Homebrew/bin /usr/local/Homebrew/etc /usr/local/Homebrew/include /usr/local/Homebrew/lib /usr/local/Homebrew/sbin /usr/local/Homebrew/share /usr/local/Homebrew/var /usr/local/Homebrew/opt /usr/local/Homebrew/share/zsh /usr/local/Homebrew/share/zsh/site-functions /usr/local/Homebrew/var/homebrew /usr/local/Homebrew/var/homebrew/linked /usr/local/Homebrew/Cellar /usr/local/Homebrew/Caskroom /usr/local/Homebrew/Frameworks
  /bin/chmod 755 /usr/local/Homebrew/share/zsh /usr/local/Homebrew/share/zsh/site-functions
  /bin/chmod g+rwx /usr/local/Homebrew/bin /usr/local/Homebrew/etc /usr/local/Homebrew/include /usr/local/Homebrew/lib /usr/local/Homebrew/sbin /usr/local/Homebrew/share /usr/local/Homebrew/var /usr/local/Homebrew/opt /usr/local/Homebrew/share/zsh /usr/local/Homebrew/share/zsh/site-functions /usr/local/Homebrew/var/homebrew /usr/local/Homebrew/var/homebrew/linked /usr/local/Homebrew/Cellar /usr/local/Homebrew/Caskroom /usr/local/Homebrew /usr/local/Homebrew/Frameworks
  /bin/chmod 755 /usr/local/Homebrew/share/zsh /usr/local/Homebrew/share/zsh/site-functions
  /usr/sbin/chown $ConsoleUser /usr/local/Homebrew/bin /usr/local/Homebrew/etc /usr/local/Homebrew/include /usr/local/Homebrew/lib /usr/local/Homebrew/sbin /usr/local/Homebrew/share /usr/local/Homebrew/var /usr/local/Homebrew/opt /usr/local/Homebrew/share/zsh /usr/local/Homebrew/share/zsh/site-functions /usr/local/Homebrew/var/homebrew /usr/local/Homebrew/var/homebrew/linked /usr/local/Homebrew/Cellar /usr/local/Homebrew/Caskroom /usr/local/Homebrew /usr/local/Homebrew/Frameworks
  /usr/bin/chgrp admin /usr/local/Homebrew/bin /usr/local/Homebrew/etc /usr/local/Homebrew/include /usr/local/Homebrew/lib /usr/local/Homebrew/sbin /usr/local/Homebrew/share /usr/local/Homebrew/var /usr/local/Homebrew/opt /usr/local/Homebrew/share/zsh /usr/local/Homebrew/share/zsh/site-functions /usr/local/Homebrew/var/homebrew /usr/local/Homebrew/var/homebrew/linked /usr/local/Homebrew/Cellar /usr/local/Homebrew/Caskroom /usr/local/Homebrew /usr/local/Homebrew/Frameworks
  /bin/mkdir -p /Users/$ConsoleUser/Library/Caches/Homebrew
  /bin/chmod g+rwx /Users/$ConsoleUser/Library/Caches/Homebrew
  /usr/sbin/chown $ConsoleUser /Users/$ConsoleUser/Library/Caches/Homebrew
  /bin/mkdir -p /Library/Caches/Homebrew
  /bin/chmod g+rwx /Library/Caches/Homebrew
  /usr/sbin/chown $ConsoleUser /Library/Caches/Homebrew

  # Install Homebrew as the currently logged in user
  echo "Starting Homebrew install"
  su $ConsoleUser -c "curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C /usr/local/Homebrew"
# If Homebrew is already installed then just echo that it is already installed
else
  echo "Homebrew is already installed"
fi


# Checks tempAdminStatus and removes admin rights if needed. 
if [ "$tempAdminStatus" = true ] ; then
  dscl . -delete /Groups/admin GroupMembership $ConsoleUser
  echo "Admin rights removed"
fi

beeboo
Contributor

is this via self service?

how you do you guys code in the license acceptance?

IIRC xcodebuild -license accept needs to be added to allow the installation of the build.

also, via the script for the ruby caller, it requires user interaction in terminal before continuing.

#!/bin/sh

osascript <<'EOF'
tell application "Terminal"
    activate
    do script ("yes '' | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"") in window 1
end tell
EOF


sudo xcodebuild -license accept

if sudo xcodebuild -license accept; then
    printf 'sudo xcodebuild -license accept succeeded
'
else
    printf 'sudo xcodebuild -license accept failed
'
fi


exit 0

this is what i use, but i am an admin on my machine and i run the script via sh in terminal, not in self service.

i had a user test for me that isnt an admin and gets this error

Script result: osascript 45:180: execution error: Terminal got an error: Can’t get window 1. (-1728) sudo xcodebuild -license accept xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance sudo xcodebuild -license accept xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance printf 'sudo xcodebuild -license accept failed ' sudo xcodebuild -license accept failed + exit 0

any help would be appreciated.

cgraysonCSUEB
New Contributor

Blessed Saviors
Thank you

rocket-beeswax
New Contributor

@emily Have you found a way to get around this message? I'm not sure what PPPC Configuration Profile I need to deploy to suppress it. c9238b61c4b04e858b7201049a10eebc

mwolf423
New Contributor II

@rocket-beeswax It tells you, you need to grant the jamf app (/usr/local/jamf/bin/jamf) access to terminal.app via PPPC profile

rmgmedia
New Contributor III

I've been using the first script posted by @dmarcnw to install during enrollment on Catalina, but I noticed the error below every time I try to use brew.

Error: /usr/local is not writable. You should change the
ownership and permissions of /usr/local back to your
user account:
  sudo chown -R $(whoami) /usr/local

Anybody got any idea how to correct this?