<!--
SPDX-FileCopyrightText: 2026 Contributors to brew-proxy <https://codeberg.org/HastD/brew-proxy>

SPDX-License-Identifier: Apache-2.0 OR MIT
-->

# brew-proxy

brew-proxy is a DBus-activated service that facilitates configuring a
[Homebrew](https://brew.sh/) installation on Linux more securely.

Typically, a Homebrew installation is owned by the user who initially set up
Homebrew. This is convenient but has security disadvantages:

- Any unsandboxed process run by that user can arbitrarily modify the Homebrew
  installation, including any installed executables.
- Homebrew build/install scripts have access to the user's files except to the
  extent that such access is prevented by sandboxing. Homebrew did
  [recently add sandboxing on Linux](https://brew.sh/2026/06/11/homebrew-6.0.0/#-linux-sandbox);
  however, the Linux sandboxing relies on unprivileged user namespaces, which
  have been associated with a number of security vulnerabilities, and are
  therefore disabled on some systems for security.

Additionally, standard Homebrew installations don't work well with multi-user
setups, as other users don't have the ability to manage the Homebrew
installation at all.

brew-proxy provides a different permissions model for a Homebrew installation
that's more secure and works better on multi-user systems.

## Permissions model

With brew-proxy, the `/home/linuxbrew` directory is configured to be
world-readable but writable only by a dedicated `linuxbrew` system user. This
means that commands that modify the Homebrew installation or Homebrew packages
must be run as the `linuxbrew` user. This provides a security boundary in two
directions:

- Unauthorized users cannot modify the Homebrew installation or packages.
- Homebrew package install scripts do not have access to other users' home
  directories.

To make it more convenient for authorized users to manage the Homebrew
installation, brew-proxy provides a DBus-activated service, `brew-proxy-daemon`,
that runs on demand as the `linuxbrew` user, executing `brew` commands on behalf
of authorized users.

Any user can run the provided `brew-proxy` command, which accepts `brew`
commands and forwards the request over DBus to `brew-proxy-daemon`. The daemon
is integrated with Polkit and requires the user to authenticate for certain
commands:

- Informational commands that do not modify the brew installation (such as
  `brew list`, `brew info`, `brew search`, and so on) can be run by all users
  without authentication.
- Certain maintainence commands like `brew update`, `brew upgrade`, and
  `brew cleanup` can be executed without authentication by users in the
  `brewadmin` or `linuxbrew` groups. Other users must authenticate as an
  administrator to run these commands.
- Other commands that modify the brew installation (including any commands that
  install or uninstall packages) can be executed without authentication only by
  users in the `linuxbrew` group.

To run non-interactively, run the client with the environment variable
`BREW_PROXY_NONINTERACTIVE=1` set. In this mode, access is automatically denied
if authentication would be required. This can be useful, for example, if a brew
command is invoked in a service running in the background.

When running multiple commands in a row that modify the Homebrew installation,
it may be convenient to instead run `run0 -u linuxbrew` to start a shell as the
`linuxbrew` user.

## Installation

An RPM package built from the specfile at `brew-proxy.spec` is available in a
[Copr repo](https://copr.fedorainfracloud.org/coprs/amaranth/homebrew/).

Alternatively, you can manually compile and install brew-proxy as follows:

1. Clone this git repository.
2. Run `meson setup build -Dprefix=/usr` and `meson compile -C build` from the
   repository root.
3. Install the project with `meson install -C build`.

## Setup

To patch your Homebrew installation so that `/home/linuxbrew` is owned by the
`linuxbrew` user and `brew` commands run by users other than `linuxbrew` are
automatically forwarded to `brew-proxy`, run the script at
`/usr/libexec/brew-proxy/brew-proxy-setup.sh` as root. For convenience, a
systemd service, `brew-proxy-setup.service`, is also provided that runs this
script once. (An opt-out is provided: if the environment variable
`NO_BREW_PROXY=1` is set, `brew-proxy` will be bypassed.)

Additionally, if you want a user to be able to run Homebrew maintainence
commands without authenticating, add them to the `brewadmin` group.

If you want a user to be able to run _any_ Homebrew command without
authenticating, you can add them to the `linuxbrew` group. This is a security
degradation and is not recommended.

## Additional notes

- brew-proxy is not an official part of Homebrew and does not claim to be
  endorsed by the Homebrew developers.
- brew-proxy does not isolate parts of the Homebrew installation from each
  other; that is, Homebrew package install scripts can still arbitrarily modify
  the Homebrew installation.
- `brew-proxy-daemon` runs the requested brew commands in a PTY and passes a
  file descriptor of the PTY over DBus back to the client who requested the
  command. All brew commands are initialized with standard input closed, so the
  client cannot interact with the commands. However, the client can cancel a
  running command by pressing Ctrl+C in the terminal to interrupt the process by
  hanging up the PTY.
