<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[ LVLX – KI für den Mittelstand ]]></title>
    <description><![CDATA[ LVLX aus Langen (Rhein-Main) hebt kleine und mittelständische Unternehmen auf das nächste Level: KI und klassische Lösungen, bewusst bewertet. 22+ Jahre Erfahrung aus dem Bankenumfeld, ISO-konform und DSGVO-fest. ]]></description>
    <link>https://lvlx.io/</link>
    <atom:link href="https://lvlx.io/rss.xml" rel="self" type="application/rss+xml"/>
    <generator>Quarkus Roq</generator>
    <lastBuildDate>Wed, 02 Sep 2026 00:00:00 +0000</lastBuildDate>
      <item>
        <title><![CDATA[Homebrew auf dem Mehrbenutzer-Mac]]></title>
        <link>https://lvlx.io/posts/homebrew-auf-dem-mehrbenutzer-mac/</link>
        <guid isPermaLink="false">https://lvlx.io/posts/homebrew-auf-dem-mehrbenutzer-mac/</guid>
        <pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[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.]]></description>
        <content:encoded><![CDATA[<div class="paragraph">
<p>Zwei Personen nutzen denselben Mac. Beide sind Administratoren. Eine von beiden hat Homebrew
installiert, und die andere kann jetzt nichts mehr installieren:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">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</code></pre>
</div>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>Im Folgenden heißen die beiden Menschen <code>alice</code> (uid 501) und <code>bob</code> (uid 502), beide in der
Gruppe <code>admin</code>. Homebrew 6.0.20, Apple Silicon, Installationsverzeichnis <code>/opt/homebrew</code> (in
Homebrews Dokumentation „prefix“, abfragbar mit <code>brew --prefix</code>).</p>
</div>
<div class="sect1">
<h2 id="_was_der_installer_tatsächlich_hinterlässt">Was der Installer tatsächlich hinterlässt</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Die Rechtestruktur ist nicht kaputt, sondern genau das, was der offizielle Installer
erzeugt. Er führt <code>chmod ug=rwx</code> über eine Liste von Unterverzeichnissen aus, macht also aus
<code>755</code> ein <code>775</code>, lässt aber das Installationsverzeichnis selbst und das Git-Checkout auf
<code>755</code>:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 37.5%;">
<col style="width: 12.5%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Pfad</th>
<th class="tableblock halign-left valign-top">Modus</th>
<th class="tableblock halign-left valign-top">Eigentümer:Gruppe</th>
<th class="tableblock halign-left valign-top">Zweiter Admin darf schreiben?</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">755</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Nein</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew/.git</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">755</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Nein</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew/Library</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">755</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Nein</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew/docs</code>, <code>completions</code>, <code>manpages</code>, <code>package</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">755</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Nein</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew/bin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">775</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ja</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew/Cellar</code>, <code>Caskroom</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">775</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ja</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/opt/homebrew/{etc,lib,opt,share,var,include,sbin,Frameworks}</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">775</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bob:admin</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ja</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Ein zweiter Admin kann über die Gruppe <code>admin</code> in den Cellar und nach bin schreiben, aber
nicht ins Installationsverzeichnis selbst und nicht ins Git-Checkout: Die stehen auf <code>755</code>,
und dort hilft Gruppenmitgliedschaft nicht. Deshalb scheitert es nicht sauber, sondern halb
und verwirrend.</p>
</div>
<div class="paragraph">
<p>Die Dokumentation beschreibt dabei eine Einheitlichkeit, die der Installer gar nicht
herstellt. <code>docs/FAQ.md</code> behauptet, die Rechte seien durchgehend <code>0755</code>, unter macOS wie
unter Linux; die <code>775</code>-Zeilen oben sagen etwas anderes.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_homebrew_unterstützt_das_nicht">Homebrew unterstützt das nicht</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Bei gemeinsam genutzten Installationen hilft Ihnen das Projekt nicht.
<code>docs/Support-Tiers.md</code> führt sie unter <strong>Unsupported configurations</strong> 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:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>If you need to run Homebrew in a multi-user environment, consider creating a separate user
account specifically for use of Homebrew.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>Dieser Satz stand wirklich einmal in der offiziellen Dokumentation. Und er ist verschwunden.
Commit <code>db70c09e1a</code> 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.</p>
</div>
<div class="paragraph">
<p>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: <code>/opt/homebrew/docs</code> und die vollständige Historie in
<code>/opt/homebrew/.git</code>.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_warum_nicht_die_naheliegenden_alternativen">Warum nicht die naheliegenden Alternativen</h2>
<div class="sectionbody">
<div class="paragraph">
<p><strong>group-write plus vererbbare ACLs.</strong> Wirklich bequem, und es funktioniert. <code>chmod -R g+w</code>
allein reicht nicht: Das nächste <code>brew install</code> legt Dateien unter <code>umask 022</code> an, und der
andere Benutzer ist binnen Tagen wieder ausgesperrt. Sie brauchen macOS-ACLs mit
<code>file_inherit</code> und <code>directory_inherit</code>, dazu <code>git config --system --add safe.directory
/opt/homebrew</code>, weil das Repository jemand anderem gehört. Das ist exakt die Konfiguration,
die <code>Support-Tiers.md</code> als nicht unterstützt führt, und Homebrews eigener Code, der Rechte
geradezieht, setzt <code>chmod 755</code>. Jede künftige <code>brew</code>-Version kann Ihre Arbeit also wieder
einreißen.</p>
</div>
<div class="paragraph">
<p><strong>Ein eigenes Installationsverzeichnis pro Benutzer unter <code>~/homebrew</code>.</strong> Auf Apple Silicon
fatal. Bottles werden ausschließlich für <code>/opt/homebrew</code> gebaut, bei einem abweichenden Pfad
wird daher alles aus dem Quelltext kompiliert. Die FAQ formuliert es als „Pick another
prefix at your peril!“</p>
</div>
<div class="paragraph">
<p><strong>Nichts tun.</strong> 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.</p>
</div>
<div class="paragraph">
<p>Der Service-Account kostet ein <code>sudo</code> 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 <code>chown</code>-Befehlen bestand. Genau das gab den
Ausschlag gegen die ACL-Variante.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_die_lösung_ein_eigener_service_account">Die Lösung: ein eigener Service-Account</h2>
<div class="sectionbody">
<div class="imageblock diagram">
<div class="content">
<img src="cover.svg" alt="Vorher: bob gehört /opt/homebrew, alice darf deshalb in bin und Cellar schreiben, aber nicht ins Installationsverzeichnis selbst und nicht ins Git-Checkout. Nachher: ein versteckter Service-Account besitzt das gesamte Verzeichnis, und beide Menschen installieren über sudo.">
</div>
<div class="title">Figure 1. Besitzverhältnisse vorher und nachher: ein Mensch besitzt das Installationsverzeichnis, gegenüber einem Service-Account, durch den beide Menschen hindurchgehen</div>
</div>
<div class="paragraph">
<p>Ein einziges Konto, <code>_homebrew</code>, hinter dem kein Mensch steht, besitzt das gesamte
Installationsverzeichnis. Menschen rufen <code>brew</code> über <code>sudo -u</code> auf. Keine ACLs, kein
group-write, kein <code>safe.directory</code>, kein Ärger mit der umask, und die Besitzverhältnisse
verschieben sich nie.</p>
</div>
<div class="paragraph">
<p>Der führende Unterstrich ist Apples Konvention für Service-Accounts (<code><em>www</code>, <code>_mysql</code>). Der
praktische Nutzen: Die übliche Methode, menschliche Benutzer aufzulisten, <code>dscl . -list
/Users | grep -v '^</em>'</code>, filtert das Konto automatisch heraus. Homebrew hat den Kontonamen
nirgends fest verdrahtet, Sie können ihn also frei wählen.</p>
</div>
<div class="sect2">
<h3 id="_kein_login_sind_vier_unabhängige_stellschrauben">„Kein Login“ sind vier unabhängige Stellschrauben</h3>
<div class="paragraph">
<p>Hier geht es am häufigsten schief.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 40%;">
<col style="width: 60%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Stellschraube</th>
<th class="tableblock halign-left valign-top">Wirkung</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>IsHidden 1</code> und <code>HiddenUsersList</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Blenden das Konto aus Anmeldefenster und schnellem Benutzerwechsel aus, wirken aber erst ab der nächsten Abmeldung. Rein kosmetisch; das Konto bleibt voll nutzbar.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Nie ein Passwort gesetzt</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Keine Anmeldung möglich. <code>sudo -u</code> braucht das Passwort des Zielkontos nicht, das kostet also nichts.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UserShell /usr/bin/false</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Keine interaktive Shell. <strong>Bricht <code>sudo -u &#8230;&#8203; -i</code>.</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uid &lt; 500</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Wird automatisch aus dem Anmeldefenster ausgeblendet.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Die Falle: <code>sudo -u X -i</code> startet ausdrücklich die Login-Shell von X. Ausgerechnet der
naheliegendste Weg, ein Konto für Logins zu sperren, nämlich die Shell auf <code>/usr/bin/false</code>
zu setzen, zerstört genau den Aufruf, auf dem diese Lösung beruht.</p>
</div>
<div class="paragraph">
<p>Dieser Text nimmt deshalb eine echte Shell (<code>/bin/zsh</code>), kein Passwort und <code>IsHidden 1</code>.
Anmelden kann sich trotzdem niemand, weil es gar keine Credentials gibt, und <code>sudo -u
_homebrew -i</code> liefert ein korrektes <code>HOME</code> und <code>PATH</code>. Wer stattdessen bei <code>/usr/bin/false</code>
bleiben will, muss <code>-i</code> durch <code>-H</code> ersetzen: Sonst zeigt <code>HOME</code> auf das Home-Verzeichnis des
Aufrufers, und brew schreibt seinen Cache dorthin statt nach <code>/Users/_homebrew</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_wählen_sie_eine_uid_oberhalb_von_500">Wählen Sie eine uid oberhalb von 500</h3>
<div class="paragraph">
<p>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 <code>_oahd</code>, der Rosetta-2-Daemon, allein auf 441. Auf den dichten
Block beschränkt Apple sich also nicht.</p>
</div>
<div class="paragraph">
<p>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 <code>ls -l</code> 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.</p>
</div>
<div class="paragraph">
<p>Der einzige Vorteil von unter 500 ist das automatische Ausblenden aus dem Anmeldefenster,
und das erledigt <code>IsHidden 1</code> ohnehin. Nehmen Sie 700 oder irgendeinen anderen Wert über
500, der von Ihren menschlichen Konten frei ist.</p>
</div>
</div>
<div class="sect2">
<h3 id="_zwei_weitere_voraussetzungen">Zwei weitere Voraussetzungen</h3>
<div class="paragraph">
<p>Wenn Sie Casks installieren, muss das Konto in der Gruppe <code>admin</code> sein. <code>/Applications</code>
gehört <code>root:admin</code> bei <code>drwxrwxr-x</code>, ein Service-Account mit der Primärgruppe <code>staff</code> kann
dort also kein App-Bundle anlegen oder ersetzen. Der Preis dafür: <code>admin</code> gewährt über
Apples <code>%admin ALL=(ALL) ALL</code> 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.</p>
</div>
<div class="paragraph">
<p>Das Konto braucht außerdem ein echtes Home-Verzeichnis. Apples Daemons bekommen oft
<code>/var/empty</code>, Homebrew dagegen braucht ein beschreibbares <code>$HOME</code> für
<code>~/Library/Caches/Homebrew</code>. Daran scheitert, wer das Konto besonders minimal halten will.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_umsetzung">Umsetzung</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Vorab prüfen. Alle drei Befehle sollten nichts ausgeben:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">dscacheutil -q user  -a name _homebrew
dscacheutil -q group -a name _homebrew
dscacheutil -q user  -a uid  700</code></pre>
</div>
</div>
<div class="paragraph">
<p>Konto anlegen und einrichten. Ohne <code>-password</code> wird nie ein Passwort gesetzt, das Konto kann
sich also nicht authentifizieren:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">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</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>sysadminctl</code> ersetzt die achtteilige <code>dscl . -create</code>-Folge, die dafür sonst herumgereicht
wird. Dass kein Passwort gesetzt wurde, bestätigt <code>dscl . -read /Users/_homebrew
AuthenticationAuthority</code>: Dort darf kein <code>ShadowHash</code> auftauchen.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>Die verbreitete Anleitung nennt nur <code>IsHidden</code>. Auf Darwin 25.6 verschwand <code>_homebrew</code> aus
dem Anmeldefenster erst, nachdem <code>IsHidden 1</code>, der Eintrag in <code>HiddenUsersList</code> und eine
Abmeldung zusammengekommen waren. Ob einer der beiden Schalter allein genügt, wurde nicht
getrennt geprüft; ohne die Abmeldung wirkte keiner von beiden. Wer gleich nach den Befehlen
ins Anmeldefenster schaut, hält sie deshalb für wirkungslos.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Installationsverzeichnis übergeben, dazu alle App-Bundles bereits installierter Casks:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">sudo chown -R _homebrew:admin /opt/homebrew

# eine Zeile je bereits installiertem Cask
sudo chown -R _homebrew:admin /Applications/Obsidian.app</code></pre>
</div>
</div>
<div class="paragraph">
<p>Dann der Alias, für jeden menschlichen Benutzer:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">echo "alias brewer='sudo -u _homebrew -i /opt/homebrew/bin/brew'" &gt;&gt; ~/.zshrc</code></pre>
</div>
</div>
<div class="paragraph">
<p>Bewusst nicht <code>brew</code> genannt, damit lesende Befehle unprivilegiert bleiben. Absoluter Pfad
statt <code>PATH</code>-Auflösung, weil <code>/etc/paths.d/homebrew</code> von <code>path_helper</code> angehängt wird und
hinter <code>/usr/bin</code> landen kann.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>Für das neue Konto müssen Sie vermutlich kein <code>PATH</code> einrichten: Legt der Installer
<code>/etc/paths.d/homebrew</code> an, findet jede Login-Shell <code>brew</code> über <code>path_helper</code> bereits, auch
die aus <code>sudo -u _homebrew -i</code>. Prüfen Sie das, bevor Sie dem Service-Account eine
<code>.zprofile</code> verpassen.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="_prüfen">Prüfen</h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">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 &amp;&amp; wget --version | head -1 &amp;&amp; brewer uninstall wget</code></pre>
</div>
</div>
<div class="paragraph">
<p>Zwei Mechanismen sollte man nachprüfen statt voraussetzen. Homebrews Schutz gegen
root-Aufrufe in <code>Library/Homebrew/brew.sh</code> greift wirklich nur bei root:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">check-run-command-as-root() {
  [[ "${EUID}" == 0 || "${UID}" == 0 ]] || return</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>sudo -u _homebrew</code> setzt reale und effektive uid auf 700 und nicht auf 0, kommt also durch.
<code>sudo brew</code> wird rundheraus abgelehnt.</p>
</div>
<div class="paragraph">
<p>Und Dateien, die unter <code>sudo -u _homebrew</code> entstehen, gehören <code>_homebrew</code> und nicht root.
sudo setzt beide uids auf das Zielkonto; root ist nur die kurze Zwischenstation, die den
Wechsel vollzieht. Da nur <code>_homebrew</code> schreibt, bleiben die Besitzverhältnisse einheitlich,
ganz ohne group-write und ohne ACLs.</p>
</div>
<div class="paragraph">
<p>Zuletzt sind die Caches in den beiden Home-Verzeichnissen nur noch Ballast:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">rm -rf ~/Library/Caches/Homebrew</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_der_alltag_damit">Der Alltag damit</h2>
<div class="sectionbody">
<div class="paragraph">
<p><strong><code>brewer</code> installiert, das nackte <code>brew</code> liest.</strong> Nehmen Sie <code>brewer</code> für <code>install</code>,
<code>uninstall</code>, <code>upgrade</code>, <code>update</code>, <code>cleanup</code>, <code>tap</code> und <code>doctor</code>. Nehmen Sie das nackte
<code>brew</code> für <code>list</code>, <code>search</code>, <code>info</code>, <code>outdated</code>, <code>deps</code> und <code>--prefix</code>. 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 <code>brew doctor</code> als Mensch jetzt <code>/opt/homebrew</code> als nicht
beschreibbar meldet, ist dabei so gewollt; die aussagekräftige Antwort gibt <code>brewer doctor</code>.</p>
</div>
<div class="paragraph">
<p><strong>Führen Sie installierte Programme niemals über <code>brewer</code> aus.</strong> Das Programm läuft dann als
<code>_homebrew</code> und schreibt seinen Zustand nach <code>/Users/_homebrew</code>. <code>brewer gpg --gen-key</code> legt
einen privaten Schlüssel an einer Stelle ab, die Sie später mühsam suchen. <code>brewer colima
start</code> legt die VM und ihren Socket unter <code>/Users/_homebrew/.colima</code> an, wo Ihr eigenes
<code>docker</code> sie nicht findet.</p>
</div>
<div class="paragraph">
<p><strong>sudo fragt nach Ihrem eigenen Passwort, nicht nach dem des Zielkontos.</strong> 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.</p>
</div>
<div class="paragraph">
<p><strong>Einen weiteren Admin aufzunehmen kostet nichts.</strong> Jedes Mitglied von <code>admin</code> ist über
<code>%admin ALL=(ALL) ALL</code> bereits berechtigt. Tragen Sie den Alias in dessen
Shell-Konfiguration ein, mehr nicht.</p>
</div>
</div>
</div><div style="margin-top: 50px; font-style: italic;"><strong><a href="https://lvlx.io/posts/homebrew-auf-dem-mehrbenutzer-mac/">Keep reading</a>.</strong></div><br /> <br />]]></content:encoded>
      </item>
  </channel>
</rss>

