homebrew
Installs Homebrew (Linuxbrew) into /home/linuxbrew/.linuxbrew, owned by an unprivileged account.
Applied by setup_new_machine.yml and, on its own, by setup-homebrew.yml.
The one thing that shapes this role
Section titled “The one thing that shapes this role”Homebrew refuses to run as root, and this fleet connects as root. So every install step escalates downwards — become_user: {{ homebrew_user }} — which needs no password in that direction. The reverse, connecting as the account and escalating to root, is what the rest of the fleet does; here it is inverted.
That account must already exist. The role checks first and says so rather than failing inside a become:
Homebrew must be installed as an unprivileged account, and unknown224 does not exist on<host>. Create it first — ansible-playbook playbooks/setup-admin-user.yml --limit <host>In setup_new_machine.yml that is guaranteed: the first play creates the account before any role runs.
Why not install.sh
Section titled “Why not install.sh”The official installer refuses to run as root, and calls sudo itself for the parts that need privilege — which prompts for a password and hangs an unattended run unless the account has passwordless sudo (admin_user_sudo_nopasswd is false by default, deliberately).
This role sidesteps that: it creates the prefix as root, owned by the account, then clones into it as the account. Nothing inside the install needs privilege, so nothing prompts.
Variables
Section titled “Variables”| Variable | Default | Effect |
|---|---|---|
homebrew_user | {{ admin_user }} → unknown224 | Account Homebrew is installed as and owned by |
homebrew_prefix | /home/linuxbrew/.linuxbrew | Install prefix |
homebrew_repo | https://github.com/Homebrew/brew | Source repository |
homebrew_prerequisites | build-essential, procps, curl, file, git, acl | Installed with apt, as root |
homebrew_update | true | Pull the repo on every run |
homebrew_configure_shell | true | Write /etc/profile.d/homebrew.sh |
homebrew_profile_script | /etc/profile.d/homebrew.sh | Where activation is written |
homebrew_packages | [] | Formulae to install once brew works |
ansible-playbook ... playbooks/setup-homebrew.yml -e '{"homebrew_packages": ["gh", "fd"]}'Details worth knowing
Section titled “Details worth knowing”aclis in the prerequisites for Ansible, not Homebrew. Without it, a task that becomes an unprivileged user from root cannot hand over its temp files and fails withFailed to set permissions on the temporary files.- The clone is not shallow, on purpose. With
depth: 1Homebrew reports its version asHomebrew >=4.3.0 (shallow or no git repository)andbrew updatewill not work against it. The full history costs a few hundred MB and a slower first clone. - A non-standard
homebrew_prefixforfeits the bottles. Homebrew ships prebuilt binaries only for the standard prefix; anywhere else, every formula compiles from source. The role asserts thatbrew --prefixmatches what was asked for. - The first run is slow — it fetches Homebrew’s portable Ruby. Budget minutes and roughly 1 GB free under
/home. Later runs are quick, and a converged host reportschanged=0. - Activation is a login-shell thing.
/etc/profile.dis not read byssh host <cmd>, cron or systemd; call/home/linuxbrew/.linuxbrew/bin/brewdirectly there, or usebash -lc.
Verified
Section titled “Verified”Against test-lxc (Debian 13), connecting as root and installing as unknown224: brew --version reports a real version, brew --prefix matches, su - unknown224 -c brew works through the profile snippet, and a second run is changed=0.