Install to /opt instead of /home/linuxbrew

That’s a good question. Linuxbrew is installed to /home to avoid requiring sudo, which is helpful for systems in which one can’t get root access, which is common for scientific computing clusters.

See also https://www.reddit.com/r/linux/comments/625koc/is_linuxbrew_needed_for_linux/dfk79p9/

That makes sense for /home/$USER/.linuxbrew but I’m referring to the fact that the default location is actually /home/linuxbrew/.linuxbrew

The install script prompts the user for sudo password, then creates a new dir in /home called linuxbrew, where it installs the whole stack. To access it, the user’s asked to add /home/linuxbrew/.linuxbrew/bin to their PATH. It works, it’s just severely non-standard.

Here’s the relevant code (with a few snips made for brevity) from the install script:

if [[ -z "${HOMEBREW_ON_LINUX-}" ]]; then
  HOMEBREW_PREFIX="/usr/local"
  HOMEBREW_REPOSITORY="/usr/local/Homebrew"
  HOMEBREW_CACHE="${HOME}/Library/Caches/Homebrew"
   [snip]
else
  HOMEBREW_PREFIX_DEFAULT="/home/linuxbrew/.linuxbrew"
  HOMEBREW_CACHE="${HOME}/.cache/Homebrew"
  [snip]
fi

If HOMEBREW_ON_LINUX is not set, then Homebrew goes to /usr/local but if it is set, then /home/linuxbrew/.linuxbrew is created and used as the base directory.

I assume the authors did this for fear of clobbering something in /usr/local, which is relatively commonly used in Linux (at least moreso than in macOS by default), but I question whether /home is the appropriate place for it. This is one reason /opt exists.

It’s so a system administrator could create a linuxbrew role account. There are other, more technically pure ways to accomplish the same goal but this is the easiest way to get a non-root setup and still deliver binary packages, some of which may be non-relocatable.

That makes some sense.

I’ll see how things go with keeping it in /opt.

Thanks @jonchang

There’s a detailed explanation here:

See also the FAQ entry “Why install in /home/linuxbrew/.linuxbrew?”, which addresses precisely this question.

@sjackman on the topic of relocatable bottles, I recently came across the reproducible-builds.org project, and was wondering if progress in the build path independence criterion could help bottles become relocatable.

And more directly related to Linuxbrew: how can one identify non-relocatable bottles and help in making them relocatable? Is there some documentation for this type of work?

on the topic of relocatable bottles, I recently came across the reproducible-builds.orgproject, and was wondering if progress in the build path independence criterion could help bottles become relocatable.

That’s definitely relevant!

And more directly related to Linuxbrew: how can one identify non-relocatable bottles and help in making them relocatable? Is there some documentation for this type of work?

I would love more bottles to be relocatable, and I believe there is low-hanging fruit and improvements to be made on this front. A relocatable bottle contains the string cellar :any in the formula, and a non-relocatable bottle does not. Pick a formula that you care about that is not currently relocatable. Install the bottle, then run brew bottle -v FORMULA. It will tell you why the bottle is not relocatable. If you’re able to fix it and make it relocatable, please open a PR! If you want to work actively on it and discuss it more, open a GitHub issue, tag me, and I’d be happy to chat.

2 Likes

A relocatable bottle contains the string cellar :any in the formula, and a non-relocatable bottle does not.

That seemed to be the case in my brief investigation, but I did find cases where this wasn’t done, e.g. in this commit. Was that an overlook, or is there more nuance to how the cellar :any bit can be used? I’m particularly confused about the following passage from the docs:

This can be omitted if a bottle is compiled (as all default Homebrew ones are) for the default HOMEBREW_CELLAR of /usr/local/Cellar.

Can you explain what this means, especially for Linuxbrew formulas?

Install the bottle, then run brew bottle -v FORMULA . It will tell you why the bottle is not relocatable.

Wow, that’s very helpful! Thanks for the tip.

If you want to work actively on it and discuss it more, open a GitHub issue, tag me, and I’d be happy to chat.

Most likely I’ll work on it occasionally rather than in a continuous effort, but I’ll make sure to ping you when I do.

The bottle block is updated automatically by the CI system. See commit https://github.com/Homebrew/linuxbrew-core/commit/fdae163144124be0f10666dd69cc689879e8d7c4

On Linux, omitting the cellar line is equivalent to cellar /home/linuxbrew/.linuxbrew/Cellar, meaning the bottle is not relocatable and can only be installed in the default cellar.

Looking forward to your PRs! Please @ me in your PRs.

1 Like

The Conda package manager ships a lot of binary packages that are fully relocatable: you can create and install environments in arbitrary locations on your system, and the precompiled binary packages will “just work” no matter what the environment prefix is. Their recipe specification file is analogous to Homebrew’s “formula”.

Maybe there are lessons to be learned from their build/packaging tool conda-build. I know that actually building a Conda package doesn’t typically require special magic, except for sometimes modifying build scripts to set prefixes and search paths, by way of a handful of specific environment variables.

Edit: couldn’t you create a linuxbrew account and just set its home directory to /opt/linuxbrew/?

I really like that idea.

It’s not uncommon to have purely technical Unix accounts with home directories outside of /home.

I don’t know very much about the FHS though.

Precisely.

And with respect to the FHS, in my opinion /opt is the perfect location for this purpose. It’s a designated place that the package manager usually doesn’t touch, and it’s generally mnemonic for “self-contained self-managed pile of stuff that isn’t part of your OS”. There’s a reason that MacPorts went with /opt as its home location.

That said, I’m a little annoyed to find that on my current Linux Mint installation APT installed some things to /usr/local, which IMO is a violation of the FHS and practically means I can no longer trust that directory to be “mine” (from a sysadmin perspective). I consider this an “upstream bug”, but it’s still important to consider that Linuxbrew must contend with a variety of ill-behaved and/or opinionated OSes. Making bottles freely relocatable is a more robust long-term solution.

1 Like

Here’s my stock response when asked why /home/linuxbrew/.linuxbrew is the default prefix:

Consider installing Linuxbrew in /home/linuxbrew/.linuxbrew/ if possible so that you can use precompiled binary packages (known as bottles) for non-relocatable formula like util-linux.
Another possible workaround for you is brew install --force-bottle util-linux, but no promises.

If it’s an option for you, you could open a ticket with your information systems department to ask that they create a linuxbrew role account with home directory /home/linuxbrew.

The precompiled binary bottles of non-relocatable bottles can only be used if you install in /home/linuxbrew/.linuxbrew, otherwise they have to be built from source. See the documentation below. On macOS the default installation directory is /usr/local. On Linux the default installation directory is /home/linuxbrew/.linuxbrew.

Edit: couldn’t you create a linuxbrew account and just set its home directory to /opt/linuxbrew/ ?

Yes, you can, but you won’t be able to use non-relocatable bottles.

1 Like

Homebrew is overly conservative in determining whether a bottle is relocatable. Work on improving those heuristics would be the singular thing that would most improve user experience for users on HPC systems without root, so that they can use more bottles.

Kinda related question.

I am in need to install the packages in a different path. I don’t care about the path of brew itself, but I do care about the path of the packages that brew will install. I don’t care about the need to re-compile the software.

What is the cleanest way to do this?

@notklaatu did you manage to install the packages in /opt? It is working fine? How did you do it?

@siscia I did install to /opt, and submitted a patch to make it easy for others:

It was not merged, as the maintainer apparently doesn’t feel there’s enough demand for that configuration. I have since migrated to pkgsrc - not out of spite or anything, but the enforced non-standard install path (and requirement for a dedicated homebrew user) is kind of a deal-breaker for the way I need to organize the systems I maintain. I wasn’t running into problems with /opt, but then again I was afraid I might in the future because it’s not a supported option, apparently.

Having said that, the install to /opt worked fine for the couple of weeks I kept with it.

You can install Homebrew in any directory of your choosing using these installation instructions: https://docs.brew.sh/Homebrew-on-Linux#alternative-installation

If I’m reading that correctly, it requires a symlink to the [re]-location for each user requiring access to the package.

Way up near the start of this post, someone mentioned that certain bottles are not relocatable, so it sounds to me like if someone maintains the base dir at /opt (or whatever), some bottle would be broken upon install.

If the bottle (precompiled binary package) is not relocatable, Homebrew will instead automatically install the package from source.

2 Likes

That’s great to know, thanks.

I understand even less now why a symlink to the user’s home directory is necessary. Is it just a hack around adding /opt or /usr/local to a user’s PATH (or, more likely, to /etc/profile)?