Apparently, openssh package has sftp-server in it and it gets installed to the store (e.g. /nix/store/6761i1m2w357mxx3p78h532w98lw989f-openssh-9.0p1/libexec/sftp-server), but it’s not linked to /run/current-system/sw/bin, presumably because in the classic FHS it’s installed in /usr/lib/openssh/sftp-server.
Two questions:
-
Is there a way to make this available somwhere?
-
More generally, by what mechanism do things end up in /run/current-system/sw/bin anyway?
So in theory the libexec
folder is supposed to contain binaries used by programs but not by users as pointed out here
By contrast, if something is put in /usr/libexec/
it’s a clear indication that it’s considered an internal implementation detail, and calling it directly as an end user isn’t officially supported.
You may still decide to access those binaries directly anyway, you just won’t get any support or sympathy from the platform provider if a future upgrade breaks the private interfaces you’re using.
I don’t really know why openssh does not want the user to use sftp-server (you can ask them directly) but if you really want to have it available in your path, you can add in your list of packages something like that (not tested, you may need to adjust it a bit):
(runCommand "sftp-server" {} ''
mkdir -p $out/bin
ln -s ${openssh}/libexec/sftp-server $out/bin
'';)
Regarding your second question, nix builds a derivation with symlinks to bin, lib… for the current system and an activation script will link this derivation to /run/current-system
.
More precisely:
- The packages, configured via
environment.systemPackages
are grouped into a derivation called ${config.system.path}
thanks to buildEnv
. Note in particalar the paths
that correspond to the packages to group and the pathToLink
input that corresponds to the folders (lib
, bin
…) that will be symlinked. The exact code of buildEnv is not really important: what matters is that it outputs a derivation where all folders in pathToLink
(bin/lib…
) of all the inputs are combined into each folder. So at the end $out/bin
contains all the binaries $pkg/bin
of the installed packages.
- then, a derivation is created that will symlink the packages configured in the
${config.system.path}
to $out/sw
and it will also symlink other stuff like the configuration link $out/etc
to the configuration spec and more…
- in particular, the derivation also contains an activation script
$out/activate
that, when executed, notably links the current derivation to /run/current
(code: script itself, option name system.activationScripts.script
, input to derivation and copy) and a script switch-to-configuration.pl
that call $out/activate
.
- This final derivation is then called
system.build.toplevel
(after some minor modifications to change some dependencies) and added in the top level package list as the system
package.
- Finally, when you call
nixos-rebuild switch
, you actually call the switch-to-configuration.pl
script defined above (see that it takes the derivation system
).
1 Like
Ok, I think I finished to explain the switch process! For those of you wondering how I came up with that (I am definitely not a nix developer and I also did it to familiarize with nix) I simply used NixOS Search as an entry point to locate the file that was dealing with environment.systemPackages
and I did the rest using a local copy of nixpkgs and with the great rg
(better grep) to search through the repository. (I love nix for how easy it is to go through its code)
Nice explanation, thanks @tobiasBora!