Homebrew auf dem Mehrbenutzer-Mac
Homebrew unterstützt keine gemeinsam genutzten Installationen. Warum ein zweiter Admin-Benutzer ausgesperrt wird und wie ein eigener Service-Account das behebt, ohne die von Homebrew unterstützte Konfiguration zu verlassen.
Zwei Personen nutzen denselben Mac. Beide sind Administratoren. Eine von beiden hat Homebrew installiert, und die andere kann jetzt nichts mehr installieren:
Error: /opt/homebrew is not writable. You should change the ownership
and permissions of /opt/homebrew back to your user account:
sudo chown -R $(whoami) /opt/homebrew
Der vorgeschlagene Befehl ist in dieser Situation falsch. Er verschiebt das Problem nur auf das andere Konto, und nächste Woche stehen Sie wieder hier, nur mit vertauschten Namen.
Im Folgenden heißen die beiden Menschen alice (uid 501) und bob (uid 502), beide in der
Gruppe admin. Homebrew 6.0.20, Apple Silicon, Installationsverzeichnis /opt/homebrew (in
Homebrews Dokumentation „prefix“, abfragbar mit brew --prefix).
Was der Installer tatsächlich hinterlässt
Die Rechtestruktur ist nicht kaputt, sondern genau das, was der offizielle Installer
erzeugt. Er führt chmod ug=rwx über eine Liste von Unterverzeichnissen aus, macht also aus
755 ein 775, lässt aber das Installationsverzeichnis selbst und das Git-Checkout auf
755:
| Pfad | Modus | Eigentümer:Gruppe | Zweiter Admin darf schreiben? |
|---|---|---|---|
|
755 |
|
Nein |
|
755 |
|
Nein |
|
755 |
|
Nein |
|
755 |
|
Nein |
|
775 |
|
Ja |
|
775 |
|
Ja |
|
775 |
|
Ja |
Ein zweiter Admin kann über die Gruppe admin in den Cellar und nach bin schreiben, aber
nicht ins Installationsverzeichnis selbst und nicht ins Git-Checkout: Die stehen auf 755,
und dort hilft Gruppenmitgliedschaft nicht. Deshalb scheitert es nicht sauber, sondern halb
und verwirrend.
Die Dokumentation beschreibt dabei eine Einheitlichkeit, die der Installer gar nicht
herstellt. docs/FAQ.md behauptet, die Rechte seien durchgehend 0755, unter macOS wie
unter Linux; die 775-Zeilen oben sagen etwas anderes.
Homebrew unterstützt das nicht
Bei gemeinsam genutzten Installationen hilft Ihnen das Projekt nicht.
docs/Support-Tiers.md führt sie unter Unsupported configurations auf, in einer Liste
mit Beowulf-Clustern und Toastern, und die FAQ nennt Homebrew an zwei Stellen „primarily
designed for single-user use“. Früher stand dort noch ein Ausweg:
If you need to run Homebrew in a multi-user environment, consider creating a separate user account specifically for use of Homebrew.
Dieser Satz stand wirklich einmal in der offiziellen Dokumentation. Und er ist verschwunden.
Commit db70c09e1a vom 01.01.2026, „docs: clarify Homebrew is not recommended for
multi-user environments“, hat beide Sätze gestrichen, in denen die Empfehlung stand, und sie
durch eine reine Feststellung der Einschränkung ersetzt. Das war eine Rücknahme und keine
Umformulierung: Für Mehrbenutzer-Setups empfiehlt das Projekt jetzt gar nichts mehr.
Wer heute nach dieser Empfehlung sucht, bekommt sie von Suchergebnissen und
KI-Zusammenfassungen trotzdem noch als aktuelle Dokumentation. Löschungen sind in
zwischengespeicherten Kopien unsichtbar. Verlässlich ist nur, was mit Ihrer Installation
ausgeliefert wird: /opt/homebrew/docs und die vollständige Historie in
/opt/homebrew/.git.
Der eigene Service-Account ist damit undokumentiert, aber unwidersprochen. Er hält genau die Form ein, für die Homebrew gebaut und getestet ist: einen einzigen Benutzer, dem alles gehört.
Warum nicht die naheliegenden Alternativen
group-write plus vererbbare ACLs. Wirklich bequem, und es funktioniert. chmod -R g+w
allein reicht nicht: Das nächste brew install legt Dateien unter umask 022 an, und der
andere Benutzer ist binnen Tagen wieder ausgesperrt. Sie brauchen macOS-ACLs mit
file_inherit und directory_inherit, dazu git config --system --add safe.directory
/opt/homebrew, weil das Repository jemand anderem gehört. Das ist exakt die Konfiguration,
die Support-Tiers.md als nicht unterstützt führt, und Homebrews eigener Code, der Rechte
geradezieht, setzt chmod 755. Jede künftige brew-Version kann Ihre Arbeit also wieder
einreißen.
Ein eigenes Installationsverzeichnis pro Benutzer unter ~/homebrew. Auf Apple Silicon
fatal. Bottles werden ausschließlich für /opt/homebrew gebaut, bei einem abweichenden Pfad
wird daher alles aus dem Quelltext kompiliert. Die FAQ formuliert es als „Pick another
prefix at your peril!“
Nichts tun. Ein Mensch besitzt Homebrew, die andere Person führt die installierten Programme aus (die sind für alle les- und ausführbar) und bittet um Installationen. Kein Risiko, voll unterstützt, mäßig lästig.
Der Service-Account kostet ein sudo pro Installation und hält die Maschine dauerhaft in
einer Konfiguration, die Homebrew unterstützt. Prüfen Sie vor der Entscheidung, wie groß der
Umzug überhaupt ist: Die Installation, aus der dieser Text stammt, enthielt drei Formulae
und ein Cask, womit der gesamte Umzug aus zwei chown-Befehlen bestand. Genau das gab den
Ausschlag gegen die ACL-Variante.
Die Lösung: ein eigener Service-Account
Ein einziges Konto, _homebrew, hinter dem kein Mensch steht, besitzt das gesamte
Installationsverzeichnis. Menschen rufen brew über sudo -u auf. Keine ACLs, kein
group-write, kein safe.directory, kein Ärger mit der umask, und die Besitzverhältnisse
verschieben sich nie.
Der führende Unterstrich ist Apples Konvention für Service-Accounts (www, _mysql). Der
praktische Nutzen: Die übliche Methode, menschliche Benutzer aufzulisten, dscl . -list
/Users | grep -v '^', filtert das Konto automatisch heraus. Homebrew hat den Kontonamen
nirgends fest verdrahtet, Sie können ihn also frei wählen.
„Kein Login“ sind vier unabhängige Stellschrauben
Hier geht es am häufigsten schief.
| Stellschraube | Wirkung |
|---|---|
|
Blenden das Konto aus Anmeldefenster und schnellem Benutzerwechsel aus, wirken aber erst ab der nächsten Abmeldung. Rein kosmetisch; das Konto bleibt voll nutzbar. |
Nie ein Passwort gesetzt |
Keine Anmeldung möglich. |
|
Keine interaktive Shell. Bricht |
uid < 500 |
Wird automatisch aus dem Anmeldefenster ausgeblendet. |
Die Falle: sudo -u X -i startet ausdrücklich die Login-Shell von X. Ausgerechnet der
naheliegendste Weg, ein Konto für Logins zu sperren, nämlich die Shell auf /usr/bin/false
zu setzen, zerstört genau den Aufruf, auf dem diese Lösung beruht.
Dieser Text nimmt deshalb eine echte Shell (/bin/zsh), kein Passwort und IsHidden 1.
Anmelden kann sich trotzdem niemand, weil es gar keine Credentials gibt, und sudo -u
_homebrew -i liefert ein korrektes HOME und PATH. Wer stattdessen bei /usr/bin/false
bleiben will, muss -i durch -H ersetzen: Sonst zeigt HOME auf das Home-Verzeichnis des
Aufrufers, und brew schreibt seinen Cache dorthin statt nach /Users/_homebrew.
Wählen Sie eine uid oberhalb von 500
Der Bereich unter 500 ist nicht für Dritte reserviert, sondern gehört Apple, und er füllt
sich. Auf einer aktuellen Darwin-25.6-Installation liegen Apples Service-Accounts dicht
zwischen 1 und 308, dazu _oahd, der Rosetta-2-Daemon, allein auf 441. Auf den dichten
Block beschränkt Apple sich also nicht.
Eine uid-Kollision erzeugt keinen sauberen Fehler, denn der Kernel sieht immer nur die Zahl.
Zwei Directory-Einträge mit derselben uid gelten für jede Rechteprüfung als dieselbe
Identität, und ls -l zeigt den Namen an, der zuerst aufgelöst wird. Ein künftiges
macOS-Update könnte damit irgendeinem Systemdienst Schreibrechte auf Ihr gesamtes
Installationsverzeichnis von Homebrew geben, mit einem völlig rätselhaften Symptom. Geringe
Wahrscheinlichkeit, unangenehme Folgen.
Der einzige Vorteil von unter 500 ist das automatische Ausblenden aus dem Anmeldefenster,
und das erledigt IsHidden 1 ohnehin. Nehmen Sie 700 oder irgendeinen anderen Wert über
500, der von Ihren menschlichen Konten frei ist.
Zwei weitere Voraussetzungen
Wenn Sie Casks installieren, muss das Konto in der Gruppe admin sein. /Applications
gehört root:admin bei drwxrwxr-x, ein Service-Account mit der Primärgruppe staff kann
dort also kein App-Bundle anlegen oder ersetzen. Der Preis dafür: admin gewährt über
Apples %admin ALL=(ALL) ALL nominell sudo-Rechte. Entschärft wird das dadurch, dass sich
das Konto mangels Passwort gar nicht authentifizieren kann. Es sind außerdem dieselben
Rechte, die der Mensch, der den Installer ausgeführt hat, ohnehin schon hatte.
Das Konto braucht außerdem ein echtes Home-Verzeichnis. Apples Daemons bekommen oft
/var/empty, Homebrew dagegen braucht ein beschreibbares $HOME für
~/Library/Caches/Homebrew. Daran scheitert, wer das Konto besonders minimal halten will.
Umsetzung
Vorab prüfen. Alle drei Befehle sollten nichts ausgeben:
dscacheutil -q user -a name _homebrew
dscacheutil -q group -a name _homebrew
dscacheutil -q user -a uid 700
Konto anlegen und einrichten. Ohne -password wird nie ein Passwort gesetzt, das Konto kann
sich also nicht authentifizieren:
sudo sysadminctl -addUser _homebrew -fullName "Homebrew" -UID 700 \
-shell /bin/zsh -home /Users/_homebrew
sudo mkdir -p /Users/_homebrew
sudo chown -R _homebrew:staff /Users/_homebrew
sudo chmod 755 /Users/_homebrew
# uid 700 liegt über der Grenze von 500, ab der automatisch ausgeblendet wird
sudo dscl . -create /Users/_homebrew IsHidden 1
sudo defaults write /Library/Preferences/com.apple.loginwindow \
HiddenUsersList -array-add _homebrew
# Gruppe admin, damit Casks nach /Applications schreiben dürfen
sudo dseditgroup -o edit -a _homebrew -t user admin
sysadminctl ersetzt die achtteilige dscl . -create-Folge, die dafür sonst herumgereicht
wird. Dass kein Passwort gesetzt wurde, bestätigt dscl . -read /Users/_homebrew
AuthenticationAuthority: Dort darf kein ShadowHash auftauchen.
|
Note
|
Die verbreitete Anleitung nennt nur |
Installationsverzeichnis übergeben, dazu alle App-Bundles bereits installierter Casks:
sudo chown -R _homebrew:admin /opt/homebrew
# eine Zeile je bereits installiertem Cask
sudo chown -R _homebrew:admin /Applications/Obsidian.app
Dann der Alias, für jeden menschlichen Benutzer:
echo "alias brewer='sudo -u _homebrew -i /opt/homebrew/bin/brew'" >> ~/.zshrc
Bewusst nicht brew genannt, damit lesende Befehle unprivilegiert bleiben. Absoluter Pfad
statt PATH-Auflösung, weil /etc/paths.d/homebrew von path_helper angehängt wird und
hinter /usr/bin landen kann.
|
Note
|
Für das neue Konto müssen Sie vermutlich kein |
Prüfen
id _homebrew # uid=700(_homebrew) ... 80(admin)
sudo dscl . -read /Users/_homebrew IsHidden # 1
defaults read /Library/Preferences/com.apple.loginwindow HiddenUsersList # (_homebrew)
ls -ld /opt/homebrew # _homebrew admin
brewer --version # fragt nach IHREM Passwort, nicht dem von _homebrew
brewer update # kein "dubious ownership" mehr
brewer doctor # sauber
brew list # funktioniert weiterhin ohne sudo
su - _homebrew # abgelehnt: es gibt keine Credentials
brewer install wget && wget --version | head -1 && brewer uninstall wget
Zwei Mechanismen sollte man nachprüfen statt voraussetzen. Homebrews Schutz gegen
root-Aufrufe in Library/Homebrew/brew.sh greift wirklich nur bei root:
check-run-command-as-root() {
[[ "${EUID}" == 0 || "${UID}" == 0 ]] || return
sudo -u _homebrew setzt reale und effektive uid auf 700 und nicht auf 0, kommt also durch.
sudo brew wird rundheraus abgelehnt.
Und Dateien, die unter sudo -u _homebrew entstehen, gehören _homebrew und nicht root.
sudo setzt beide uids auf das Zielkonto; root ist nur die kurze Zwischenstation, die den
Wechsel vollzieht. Da nur _homebrew schreibt, bleiben die Besitzverhältnisse einheitlich,
ganz ohne group-write und ohne ACLs.
Zuletzt sind die Caches in den beiden Home-Verzeichnissen nur noch Ballast:
rm -rf ~/Library/Caches/Homebrew
Der Alltag damit
brewer installiert, das nackte brew liest. Nehmen Sie brewer für install,
uninstall, upgrade, update, cleanup, tap und doctor. Nehmen Sie das nackte
brew für list, search, info, outdated, deps und --prefix. Die brauchen keine
Rechte: Das Installationsverzeichnis ist für alle lesbar und der Cache jedes Benutzers liegt
in dessen eigenem Home. Das erspart die Passwortabfrage bei genau den Befehlen, die Sie am
häufigsten ausführen. Dass brew doctor als Mensch jetzt /opt/homebrew als nicht
beschreibbar meldet, ist dabei so gewollt; die aussagekräftige Antwort gibt brewer doctor.
Führen Sie installierte Programme niemals über brewer aus. Das Programm läuft dann als
_homebrew und schreibt seinen Zustand nach /Users/_homebrew. brewer gpg --gen-key legt
einen privaten Schlüssel an einer Stelle ab, die Sie später mühsam suchen. brewer colima
start legt die VM und ihren Socket unter /Users/_homebrew/.colima an, wo Ihr eigenes
docker sie nicht findet.
sudo fragt nach Ihrem eigenen Passwort, nicht nach dem des Zielkontos. An dieser Asymmetrie stolpern die meisten, und genau sie macht ein Konto ganz ohne Passwort möglich. sudo merkt sich die Authentifizierung rund fünf Minuten, eine Serie von Befehlen fragt also nur einmal.
Einen weiteren Admin aufzunehmen kostet nichts. Jedes Mitglied von admin ist über
%admin ALL=(ALL) ALL bereits berechtigt. Tragen Sie den Alias in dessen
Shell-Konfiguration ein, mehr nicht.