Why doesn't e.g /bin link to /run/current-system/sw/bin?

Or more simply, why not just use /bin instead of /run/current-system/sw/bin ?

Seems like this would offer better interop with utilities that expect bash to be at e.g /bin/bash. I know there are workarounds using activationScripts, but I just want to understand the rationale.


Better interoperability would also cause more accidental cases of missed dependencies. I.e. a package would accidentally work, since it can use binaries from /bin, instead of having an explicit dependency on a package inside of /nix/store.


This isn’t an issue with dependencies as I see it, though that may be a separate issue. This is an issue of sometimes needing to specify an absolute path or not. For instance, nixos containers use systemd containers. But many of the systemd container utilities require absolute paths for binaries to run. This is already an annoyance, but it also means that nixos has totally different paths from every other system, so if I’m writing a utility that needs to be generic, I have to either assume the user has patched their nixos system, or do some other odd workaround.

Reading through the Motivation section of the original PhD thesis will explain the problems this design decision solves: https://nixos.org/~eelco/pubs/phd-thesis.pdf

And yes, this increases the packaging overhead for NixOS packages. Most NixOS users believe this is the right tradeoff.

1 Like

Thanks, Gleb - I’ll try to give it a read through soon.

I’m aware NixOS and Nix in general make a few tradeoffs (to put it mildly), most of which I enthusiastically accept - am just not fully convinced of this particular tradeoff as yet.

Frankly, anything that’s relying on specific binaries to be in exactly /bin is wrong, and should be patched. The fault is theirs, not NixOS’s.

That said, with Nix build sandboxing turned on by default these days, there’s far less need to keep /bin empty. It won’t be visible to Nix builds anyway.

1 Like

@gleber - motivation or Intro? Sorry, I didn’t see the relevant bit in a motivation section, and I’m not in a good place right now for reading through a thesis :wink:

@ElvishJerricco I mean, I agree, but the current situation just makes one have to rely on coding up how to both rely on /bin and /run/current-system/sw/bin, and detecting which to use, or find another workaround (like activationScirpts). I don’t see how one fixed directory like /run/current-system/sw/bin is better than another one like /bin.

Also, we might want to fix the systemd utilities I mentioned then, since they are a fairly ingrained part of NixOS … (thinking of machinectl in particular). But that is upstream so could be difficult.

Regarding sandboxing, I suppose you have a point; software that relies on said paths could still likely build (one would hope) but some test might fail.

Another solution would be having /bin, /usr/bin, etc. be symlinks to /run/current-system/sw/bin. However, for some reason, at least on my systems, this isn’t doable since NixOS is violating its own principle: in my /bin I have a symlink already: sh -> /nix/store/496rv6cn7n317jfbrid3662f4l7jf0is-bash-4.4-p12/bin/sh.
So there is apparently a dependence on /bin/sh being an exception to the rule already.

While doing the symlinks by default might encourage bad design, having /bin/sh be a symlink prevents what I see as a good compromise (make /bin etc. a symlink). Hmm.

Reading man system suggests /bin/sh is required by POSIX, so this path is portable.
Anyway, it is also a symlink created in an activation script so you may freely remove /bin and replace it with a symlink to /run/current-system/sw/bin if you wish so.


This is another way of saying that your program depends on something that’s usually stored in /bin, what nixpkgs (imho) tries to do is to build applications so that they will ed up using the right libs/execs/resources.
In systems like NixOS chances are that people will use your application by installing it through nix itself so there is no need for you to detect anything, just do not hardcode paths but provide a way for the packagers to customize according to the distro layout they’re packaging for.

In fact /bin and /usr/bin are privileged only because of the FHS and there is nothing wrong in the latter, the only two paths that are mandatory (that I’m aware of) are /bin/sh and /usr/bin/env.

Also, in NixOS each user can install their own version of pretty much everything, and those binaries are in /nix/var/nix/profiles/per-user/<user>/profile/, this is another reason to make the dependency you’re looking for in /bin explicit without trying to autodetect.

If you really really need to autodetect you can always use the bash builtin type e.g. type -p systemctl will return /run/current-system/sw/bin/systemctl on NixOS systems and the usual paths under the other distros

Speaking of /bin/, I believe most systems store most binaries in /usr/bin/ anyway.

@vcunat AFAIK some of the mainstream distros now link one to the other, as the distinction isn’t meaningful for quite a while now (i.e. mainframe days).