Compare commits

...

10 Commits

Author SHA1 Message Date
T. R. Bernstein
e44c48efbd Adapt to new repository 2025-10-17 23:41:52 +02:00
T. R. Bernstein
b008d4ebb0 Add module to adapt sudo settings 2025-10-17 23:41:39 +02:00
T. R. Bernstein
d4a39b5dd5 Use c app to call brew 2025-10-17 23:41:13 +02:00
T. R. Bernstein
1953b01148 Install node using volta 2025-10-17 08:04:35 +02:00
T. R. Bernstein
3f2f23a446 Create setup-user command 2025-10-16 23:25:54 +02:00
T. R. Bernstein
5c1a6998b7 Adapt homebrew installation for macOS on Intel 2025-10-16 23:21:29 +02:00
T. R. Bernstein
60fc6580d8 Make config of hostname a setup step 2025-10-16 23:20:56 +02:00
T. R. Bernstein
dd6875b79a Create setup-host command 2025-10-16 23:18:02 +02:00
T. R. Bernstein
aef49d322f Update brew install list 2025-10-16 23:17:06 +02:00
T. R. Bernstein
82e5747b67 Update MAS app list
Remove Affinity apps, as those are already installed via MDM.
2025-08-31 21:07:38 +02:00
10 changed files with 397 additions and 160 deletions

View File

@@ -1,16 +1,19 @@
# macOS System
Scripts to align a macOS system to Astzweig system configuration.
## Install
```zsh
/bin/zsh -c "$(curl -fsSL https://raw.githubusercontent.com/astzweig/macos-system/main/bootstrap.sh)"
/bin/zsh -c "$(curl -fsSL https://git.tabshift.dev/spacebar/macos-system/raw/branch/main/bootstrap.sh)"
```
## What it does
1. Run all setup from a temporary directory and delete it in the end
## Process
1. `install.sh` queries all modules for their required information
1. The modules print their required information to stdout using the format as described below.
1. `install.sh` parses those informations and tries to read them from a configuration file.
@@ -18,14 +21,17 @@ Scripts to align a macOS system to Astzweig system configuration.
1. `install.sh` then runs the modules with their required informations passed in as parameter values.
## License exclusion
The license does not cover the file [Astzweig.png](resources/user-pictures/Astzweig.png).
## Required Information Format
Modules must print their required information to stdout if they're called with
`show-questions` command. Required information are all information the module
might want to ask the user in order to configure some aspect of the system.
### Schema
The general schema is:
```zsh
@@ -33,14 +39,15 @@ The general schema is:
s: --highlight-color=What color shall your system highlight color be? # choose from: blue,red,light green;
p: --user-password=What color shall your system highlight color be?
```
The letter at the beginning is the question type:
| Question type | Description | Arguments |
| ------------- | ----------- | --------- |
| i (info) | A question where the user has no restrictions on input | `default`: a default answer. |
| p (password) | A question where the user input is not printed to standard output. | - |
| c (confirm) | A yes/no question where the user is allowed to answer yes or no. | - |
| s (select) | A list of choices where the user can select one using numbers. | `choose from`: a comma separated list of possible select values. |
| Question type | Description | Arguments |
| ------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- |
| i (info) | A question where the user has no restrictions on input | `default`: a default answer. |
| p (password) | A question where the user input is not printed to standard output. | - |
| c (confirm) | A yes/no question where the user is allowed to answer yes or no. | - |
| s (select) | A list of choices where the user can select one using numbers. | `choose from`: a comma separated list of possible select values. |
`<PARAMETER NAME>` is the the parameter name, that will receive the user answer
when the module is called. Single char parameter names will be prefixed with a
@@ -50,4 +57,5 @@ the parameter name `highlight-color` becomes `--highlight-color <user response>`
`<QUESTION>` must contain any punctuation you want to show.
[^zshlib-askUser]: Currently supported: info, password, confirm, choose. They map to [zshlib/askUser][zshlib-overview] commands.
[zshlib-overview]: https://github.com/astzweig/zshlib#whats-included

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env zsh
# vi: set ft=zsh tw=80 ts=2
function _installMASApp() {
mas install ${id} &> /dev/null
}
function installMASApp() {
local appName="$1"
local id="$2"
indicateActivity -- "Install ${appName} app" _installMASApp
}
function main() {
lop -y h1 -- -i 'Install Mac AppStore Apps'
installMASApp 'Affinity Designer 2' 1616831348
installMASApp 'Affinity Photo 2' 1616822987
installMASApp 'Affinity Publisher 2' 1606941598
installMASApp 'AusweisApp' 948660805
installMASApp 'Compressor' 424390742
installMASApp 'Developer' 640199958
installMASApp 'Diagrams' 1276248849
installMASApp 'Final Cut Pro' 424389933
installMASApp 'Iconographer Mini' 1541509510
installMASApp 'iMazing Profile Editor' 1487860882
installMASApp 'Infuse' 1136220934
installMASApp 'Keka' 470158793
installMASApp 'Keynote' 409183694
installMASApp 'Mass Rename' 1175416599
installMASApp 'Microsoft Excel' 462058435
installMASApp 'Microsoft Word' 462054704
installMASApp 'Motion' 434290957
installMASApp 'Numbers' 409203825
installMASApp 'Outbank' 1094255754
installMASApp 'Pages' 409201541
installMASApp 'Pixelmator Pro' 1289583905
installMASApp 'SnippetsLab' 1006087419
installMASApp 'WorkingHours' 1495643653
installMASApp 'Xcode' 497799835
}
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
source autoload-zshlib
main "$@"
fi

View File

@@ -1,73 +0,0 @@
#!/usr/bin/env zsh
# vi: set ft=zsh tw=80 ts=2
function configureLogging() {
local output=tostdout level=info
[ -n "${logfile}" ] && output=${logfile}
[ "${verbose}" = true ] && level=debug
lop setoutput -l ${level} ${output}
}
function getUsage() {
local cmdName=$1 text=''
read -r -d '' text <<- USAGE
Usage:
$cmdName [-v] [-d FILE] --hostname NAME
Configure host specific settings.
Options:
--hostname NAME Set NAME as current host's host name.
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
-v, --verbose Be more verbose.
----
$cmdName 0.1.0
Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG
License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law.
USAGE
print -- ${text}
}
function quitSystemPreferences() {
ps -A -o pid,comm | grep "MacOS/System Settings" | awk '{print "kill -9 " $1}' | /bin/sh
}
function setComputerName() {
scutil --set ComputerName "${hostname}"
scutil --set HostName "${hostname}"
scutil --set LocalHostName "${hostname}"
systemsetup -setcomputername "${hostname}"
systemsetup -setlocalsubnetname "${hostname}"
}
function configureComputerHostname() {
local currentComputerName="`scutil --get ComputerName`"
if [[ "${currentComputerName}" != "${hostname}" ]]; then
lop -- -i 'Hostname of computer has not been set.' -i "Will set to ${hostname}."
indicateActivity -- 'Set computer name' setComputerName
else
lop -- -i 'Hostname of computer seems to have already been set. Skipping.' -i "Hostname: $currentComputerName"
fi
}
function requireRootPrivileges() {
[[ `id -u` -eq 0 ]] || { lop -- -e 'Need root access to change hostname. Aborting.'; return 10 }
}
function main() {
local cmdPath=${1} cmdName=${1:t}
shift
eval "`getUsage $cmdName | docopts -f -V - -h - : "$@"`"
configureLogging
requireRootPrivileges || return $?
lop -y h1 -- -i 'Configure System Settings'
indicateActivity -- 'Quitting System Preferences' quitSystemPreferences
configureComputerHostname
}
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then
_DIR="${0:A:h}"
source autoload-zshlib
main $0 "$@"
fi

44
bin/azw-setup-host Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env zsh
# vi: set ft=zsh tw=80 ts=2
function _installMASApp() {
mas install ${id} &> /dev/null
}
function installMASApp() {
local appName="$1"
local id="$2"
indicateActivity -- "Install ${appName} app" _installMASApp
}
function main() {
lop -y h1 -- -i 'Install Mac AppStore Apps'
installMASApp 'AusweisApp' 948660805
installMASApp 'Compressor' 424390742
installMASApp 'Developer' 640199958
installMASApp 'Diagrams' 1276248849
installMASApp 'Final Cut Pro' 424389933
installMASApp 'Iconographer Mini' 1541509510
installMASApp 'iMazing Profile Editor' 1487860882
installMASApp 'Infuse' 1136220934
installMASApp 'Keka' 470158793
installMASApp 'Keynote' 409183694
installMASApp 'Mass Rename' 1175416599
installMASApp 'Microsoft Excel' 462058435
installMASApp 'Microsoft Word' 462054704
installMASApp 'Motion' 434290957
installMASApp 'Numbers' 409203825
installMASApp 'Outbank' 1094255754
installMASApp 'Pages' 409201541
installMASApp 'Pixelmator Pro' 1289583905
installMASApp 'SnippetsLab' 1006087419
installMASApp 'Tim' 1449619230
installMASApp 'WorkingHours' 1495643653
installMASApp 'Xcode' 497799835
}
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then
_DIR="${0:A:h}"
source autoload-zshlib
main "$@"
fi

173
bin/azw-setup-user Executable file
View File

@@ -0,0 +1,173 @@
#!/usr/bin/env zsh
# vi: set ft=zsh tw=80 ts=2
function getExecPrerequisites() {
cmds+=(
[launchctl]=''
[git]=''
[mkdir]=''
[chmod]=''
[]=''
)
}
function hideFolders() {
chflags hidden ${HOME}/bin
}
function checkExecPrerequisites() {
local -A cmds
getExecPrerequisites || return
checkCommands -m 'This script needs %1$s to work. Please install and retry.' ${(k)cmds} || return
}
function configureInstallPrefix() {
local dirPath= desc=
for dirPath desc in ${homebrew_prefix} 'Creating install prefix' ${homebrew_directory} 'Creating Homebrew directory'; do
if [[ ! -d ${dirPath} ]]; then
indicateActivity -- ${desc} createDirAndLogOnFailure ${dirPath}
fi
done
}
function createDirAndLogOnFailure() {
local dirPath=$1
mkdir -p ${dirPath} 2> /dev/null || {
loptty -- -e 'Could not create directory' -e $dirPath
return 10
}
chmod 744 ${dirPath}
}
function downloadHomebrew() {
local git_homebrew_remote=`getDefaultGitHomebrewURL`
pushd -q ${homebrew_directory} || return 10
test -d ".git" && return
git init -q
git config remote.origin.url "${git_homebrew_remote}"
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
git config core.autocrlf false
git config --replace-all homebrew.analyticsmessage false
git config --replace-all homebrew.caskanalyticsmessage false
git fetch --quiet --force origin > /dev/null
git fetch --quiet --force --tags origin > /dev/null
git reset --hard origin/master
popd -q
}
function createBrewCallerScript() {
local cmdPath=${HOME}/bin/brew
local brewPath=${homebrew_directory}/bin/brew
[[ -f ${cmdPath} ]] && rm ${cmdPath}
mkdir -p ${cmdPath:h}
cat <<- BREWCALLER > ${cmdPath}
#!/usr/bin/env zsh
export HOMEBREW_CASK_OPTS="--no-quarantine \${HOMEBREW_CASK_OPTS}"
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_ANALYTICS=1
export HOMEBREW_NO_ANALYTICS_THIS_RUN=1
export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1
"${brewPath}" "\$@"
BREWCALLER
chown $(id -un):$(id -gn) ${cmdPath}
chmod u=rwx,go=r ${cmdPath}
}
function createBrewPeriodicScript() {
local brewCallerPath=${HOME}/bin/brew
local cmdPath=${HOME}/bin/brew-periodic
[[ -f ${cmdPath} ]] && rm ${cmdPath}
mkdir -p ${cmdPath:h}
cat <<- BREWCALLER > ${cmdPath}
#!/usr/bin/env zsh
local brew='${brewCallerPath}'
\$brew update
\$brew upgrade --greedy
\$brew cleanup
BREWCALLER
chown $(id -un):$(id -gn) ${cmdPath}
chmod u=rwx,go=r ${cmdPath}
}
function updateBrew() {
local brewPath=${homebrew_directory}/bin/brew
${brewPath} update --force --quiet
chmod go-w "${homebrew_directory}/share/zsh"
}
function createLaunchDaemonsPlist() {
local uid=`id -u`
local serviceName="de.astzweig.macos.launchagents.$1"
local launchAgentPath=${HOME}/Library/LaunchAgents
local launcherPath="${launchAgentPath}/${serviceName}.plist"
[[ -d ${launchAgentPath} ]] || mkdir ${launchAgentPath} || return
[[ -f ${launcherPath} ]] && {
launchctl disable gui/${uid}/${serviceName}
rm ${launcherPath}
}
cat <<- LAUNCHDPLIST > ${launcherPath}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${serviceName}</string>
<key>ProgramArguments</key>
<array>
<string>${HOME}/bin/brew-periodic</string>
</array>
<key>StartInterval</key>
<integer>1800</integer>
</dict>
</plist>
LAUNCHDPLIST
chmod u=rw,go=r ${launcherPath}
launchctl enable gui/${uid}/${serviceName} &> /dev/null
launchctl bootstrap gui/${uid}/ ${launcherPath} &> /dev/null || true
}
function installHomebrewUpdater() {
createLaunchDaemonsPlist brew-updater
}
function getDefaultHomebrewPrefix() {
print -- ${HOMEBREW_PREFIX:-${HOME}/Library/Application Support}
}
function getHomebrewDirectoryPath() {
print -- ${homebrew_prefix:-$(getDefaultHomebrewPrefix)}/Homebrew
}
function configureFolders() {
local dirPath
for dirPath in ${HOME}/bin ${HOME}/.vim/{backups,swaps}; do
[[ ! -d ${dirPath} ]] && indicateActivity -- "Creating ${dirPath}" mkdir ${dirPath}
done
indicateActivity -- 'Hide folders' hideFolders
}
function installNode() {
volta install node
}
function main() {
lop -y h1 -- -i 'Setup User'
[[ $(id -u) -eq 0 ]] && { loptty -- -e 'Command must not be run as root.' -e $dirPath; return 16 }
configureFolders
indicateActivity -- 'Install node' installNode
local homebrew_prefix=`getDefaultHomebrewPrefix`
local homebrew_directory=`getHomebrewDirectoryPath`
checkExecPrerequisites || return 17
configureInstallPrefix || return 10
indicateActivity -- 'Downloading Homebrew' downloadHomebrew || return 11
indicateActivity -- 'Create brew caller script' createBrewCallerScript || return 12
indicateActivity -- 'Create brew periodic script' createBrewPeriodicScript || return 13
indicateActivity -- 'Update brew' updateBrew || return 14
indicateActivity -- 'Install Homebrew updater' installHomebrewUpdater || return 15
}
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then
_DIR="${0:A:h}"
source autoload-zshlib
main "$@"
fi

View File

@@ -107,7 +107,7 @@ function ensureDocopts() {
}
function cloneMacOSSystemRepo() {
local repoUrl="${MACOS_SYSTEM_REPO_URL:-https://github.com/astzweig/macos-system.git}"
local repoUrl="${MACOS_SYSTEM_REPO_URL:-https://git.tabshift.dev/spacebar/macos-system.git}"
git clone --depth 1 -q "${repoUrl}" . 2> /dev/null || return 10
[ -n "${MACOS_SYSTEM_REPO_BRANCH}" ] && git checkout -q ${MACOS_SYSTEM_REPO_BRANCH} 2> /dev/null || true
}

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env zsh
# vi: set ft=zsh tw=80 ts=2
function ensureTRBernsteinCanUpdateSystem() {
local username=$1
local sudoersFile='/etc/sudoers.d/allow-softwareupdate-for-all'
[[ -f ${sudoersFile} ]] && return
cat <<- SUDOERS > "${sudoersFile}"
trbernstein ALL=(root) NOPASSWD: /usr/sbin/softwareupdate -irR --user admin
SUDOERS
chown root:wheel "${sudoersFile}" || return 10
chmod u=rw,g=r,o= "${sudoersFile}" || return 20
}
function configure_system() {
lop -y h1 -- -i 'Configure sudoers files'
ensurePathOrLogError ${dstDir} 'Could not install binaries.' || return 10
indicateActivity -- "Allow trbernstein user to install updates using softwareupdate" ensureTRBernsteinCanUpdateSystem
}
function getExecPrerequisites() {
cmds=(
[cat]=''
[chown]=''
[chmod]=''
)
}
function getUsage() {
read -r -d '' text <<- USAGE
Usage:
$cmdName show-questions [<modkey> <modans>]...
$cmdName [-v] [-d FILE]
Add sudo rules to:
1. allow trbernstein user to install updates using softwareupdate
Options:
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
-v, --verbose Be more verbose.
----
$cmdName 0.1.0
Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG
License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law.
USAGE
print -- ${text}
}
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
_DIR="${0:A:h}"
test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 }
source "${ASTZWEIG_MACOS_SYSTEM_LIB}"
module_main $0 "$@"
fi

View File

@@ -65,6 +65,24 @@ function configureMacOSFirewall() {
${cmd} --setallowsignedapp on
}
function setComputerName() {
scutil --set ComputerName "${hostname}"
scutil --set HostName "${hostname}"
scutil --set LocalHostName "${hostname}"
systemsetup -setcomputername "${hostname}"
systemsetup -setlocalsubnetname "${hostname}"
}
function configureComputerHostname() {
local currentComputerName="`scutil --get ComputerName`"
if [[ "${currentComputerName}" != "${hostname}" ]]; then
lop -- -i 'Hostname of computer has not been set.' -i "Will set to ${hostname}."
indicateActivity -- 'Set computer name' setComputerName
else
lop -- -i 'Hostname of computer seems to have already been set. Skipping.' -i "Hostname: $currentComputerName"
fi
}
function configure_system() {
lop -y h1 -- -i 'Configure System Settings'
indicateActivity -- 'Quitting System Preferences' quitSystemPreferences
@@ -73,6 +91,13 @@ function configure_system() {
indicateActivity -- 'Configuring login window' configureLoginWindow
indicateActivity -- 'Configure global umask' launchctl config user umask 027
indicateActivity -- 'Configure macOS firewall' configureMacOSFirewall
configureComputerHostname
}
function getQuestions() {
questions=(
'i: hostname=What shall the systems hostname be?'
)
}
function getUsage() {
@@ -80,11 +105,12 @@ function getUsage() {
read -r -d '' text <<- USAGE
Usage:
$cmdName show-questions [<modkey> <modans>]...
$cmdName [-v] [-d FILE]
$cmdName [-v] [-d FILE] --hostname NAME
Set energy, network and basic preferences.
Options:
--hostname NAME Set NAME as current host's host name.
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
-v, --verbose Be more verbose.
----

View File

@@ -24,17 +24,6 @@ function ensureUserIsInAdminGroup() {
dseditgroup -o edit -a "${username}" -t user admin
}
function ensureUserCanRunPasswordlessSudo() {
local username=$1
local sudoersFile="/etc/sudoers.d/no-auth-sudo-for-${username}"
[[ -f ${sudoersFile} ]] && return
cat <<- SUDOERS > "${sudoersFile}"
Defaults:${username} !authenticate
SUDOERS
chown root:wheel "${sudoersFile}" || return 10
chmod u=rw,g=r,o= "${sudoersFile}" || return 20
}
function getFirstFreeRoleAccountID() {
local minUserID=450
local maxUserID=499
@@ -97,27 +86,87 @@ function getHomebrewRepositoryPath() {
function createBrewCallerScript() {
ensureLocalBinFolder
local username=${homebrew_username}
local brewCallerPath="/usr/local/bin/brew"
local homebrewRepositoryPath="$(getHomebrewRepositoryPath)"
local brewCallerPath="${homebrewRepositoryPath}/bin/brew-caller"
local brewCallerSymlink="/usr/local/bin/brew"
[ -f "${brewCallerPath}" ] && rm "${brewCallerPath}"
cat <<- BREWCALLER > ${brewCallerPath}
#!/usr/bin/env zsh
if [ "\$(id -un)" != "${username}" ]; then
echo 'brew will be run as ${username} user.' >&2
sudo -E -u "${username}" "\$0" "\$@"
exit \$?
fi
export HOMEBREW_CACHE="${homebrew_cache}"
export HOMEBREW_LOGS="${homebrew_log}"
export HOMEBREW_CASK_OPTS="--no-quarantine \${HOMEBREW_CASK_OPTS}"
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_ANALYTICS=1
export HOMEBREW_NO_ANALYTICS_THIS_RUN=1
export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1
umask 002
"$(getHomebrewRepositoryPath)/bin/brew" "\$@"
cat <<- BREWCALLER | clang -x c -O2 -Wall -o "${brewCallerPath}" -
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
extern char **environ;
char *format_env(const char *env_name, const char *format) {
if (!env_name || !format) return NULL;
const char *value = getenv(env_name);
if (!value) return NULL;
int formatted_len = snprintf(NULL, 0, format, value);
if (formatted_len < 0) return NULL;
char *formatted_value = malloc(formatted_len + 1);
if (!formatted_value) return NULL;
snprintf(formatted_value, formatted_len + 1, format, value);
size_t result_len = strlen(env_name) + 1 + formatted_len;
char *result = malloc(result_len + 1);
if (!result) { free(formatted_value); return NULL; }
sprintf(result, "%s=%s", env_name, formatted_value);
free(formatted_value);
return result;
}
#define HOMEBREW_USER "${username}"
#define HOMEBREW_DIR "${homebrewRepositoryPath}/bin"
#define BREW_PATH HOMEBREW_DIR "/brew"
int main(int argc, char *argv[]) {
struct passwd *pw;
uid_t target_uid;
gid_t target_gid;
pw = getpwnam(HOMEBREW_USER);
if (!pw) { fprintf(stderr, "Error: user %s not found\n", HOMEBREW_USER); return 1; }
target_uid = pw->pw_uid;
target_gid = pw->pw_gid;
char *new_environ[] = {
"PATH=" HOMEBREW_DIR "/usr/bin:/bin",
"HOMEBREW_CACHE=${homebrew_cache}",
"HOMEBREW_LOGS=${homebrew_log}",
format_env("HOME", "%s"),
format_env("HOMEBREW_CASK_OPTS", "--no-quarantine %s"),
"HOMEBREW_NO_AUTO_UPDATE=1",
"HOMEBREW_NO_ANALYTICS=1",
"HOMEBREW_NO_ANALYTICS_THIS_RUN=1",
"HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1",
NULL
};
if (setegid(target_gid) != 0) { fprintf(stderr, "setegid(%d): %s\n", target_gid, strerror(errno)); return 1; }
if (seteuid(target_uid) != 0) { fprintf(stderr, "seteuid(%d): %s\n", target_uid, strerror(errno)); return 1; }
char **newargv = malloc((argc + 1) * sizeof(char *));
if (!newargv) { fprintf(stderr, "malloc failed for new argv\n"); return 1; }
newargv[0] = (char *)BREW_PATH;
for (int i = 1; i < argc; ++i) newargv[i] = argv[i];
newargv[argc] = NULL;
umask(0002);
execve(BREW_PATH, newargv, new_environ);
fprintf(stderr, "execv(%s) failed: %s\n", BREW_PATH, strerror(errno));
return 1;
}
BREWCALLER
chown root:admin ${brewCallerPath}
chmod ug+x,o-x ${brewCallerPath}
chmod 4550 ${brewCallerPath}
ln -s "${brewCallerPath}" "${brewCallerSymlink}"
}
function createBrewPeriodicScript() {
@@ -209,7 +258,6 @@ function configure_system() {
lop -y h1 -- -i 'Install System Homebrew'
createHomebrewUserIfNeccessary || return 10
indicateActivity 'Ensure Homebrew user is in admin group' ensureUserIsInAdminGroup ${homebrew_username} || return 11
indicateActivity 'Ensure Homebrew user can run passwordless sudo' ensureUserCanRunPasswordlessSudo ${homebrew_username} || return 12
ensureHomebrewCacheDirectory || return 13
ensureHomebrewLogDirectory || return 14
indicateActivity 'Install Homebrew core' installHomebrewCore || return 15

View File

@@ -26,7 +26,9 @@ function installCasks() {
installCask devonthink
installCask firefox
installCask hazel
installCask hopper-disassembler
installCask istat-menus
installCask jdownloader
installCask launchcontrol
installCask makemkv
installCask network-radar
@@ -34,6 +36,7 @@ function installCasks() {
installCask orbstack
installCask rapidapi
installCask rectangle
installCask serverbuddy
installCask sf-symbols
installCask sketch
installCask suspicious-package
@@ -57,6 +60,7 @@ function installBrews() {
installBrew mas
if ! isDebug; then
installBrew bun
installBrew chezmoi
installBrew cocogitto
installBrew composer
installBrew curl
@@ -71,18 +75,16 @@ function installBrews() {
installBrew imap-backup
installBrew imapsync
installBrew nmap
installBrew node
installBrew pdfgrep
installBrew php
installBrew python
installBrew qpdf
installBrew rcm
installBrew ruby
installBrew 'hay-kot/scaffold-tap/scaffold'
installBrew 'lemoony/tap/snipkit'
installBrew sqlite
installBrew tree
installBrew tidy-html5
installBrew volta
installBrew yq
fi
}