Nix and the nix-shell for easily redistributable scripts
In the discussion at lobsters and the article linked in there, I
made a comment how one could use Nix and the nix-shell
in order to have
easily redistributable scripts. This post expands on it.
Nix is hermetic in the sense that its “packages” do not use dependencies from the outside and its packages do not affect the system. Furthermore, one can have multiple versions of a package in the systems at the same time.
I was explicitly talking about scripts, in a way to enable running them, such that no installation of dependencies is needed prior to running the script.
To illustrate the point, let’s say on has a script written in fish,
which relies on ripgrep and dust. Normally, the script would begin with
#!/usr/bin/env fish
. Now, that is quite a portable way of writing the
script and great practice. However, for our goal of including all the
dependencies, we need more. To that end, one can use the nix-shell
in the
shebang line, that will then be used to fetch all the dependencies (from
Nix, if they are available in the nixpkgs:
#!/usr/bin/env nix-shell
#!nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/8a3eea054838b55aca962c3fbde9c83c102b8bf2.tar.gz
#!nix-shell -i fish
#!nix-shell -p fish -p ripgrep -p dust
The first line is the regular shebang invocation which tell the system to
use the nix-shell
as the interpreter. The second line is read by the nix-shell
when it starts interpreting the script, and -I
option is there to pin the
dependencies to a particular “release” of nixpkgs. The third line (the one
with -i
) tells the nix-shell
that the actual interpreter is fish. Lastly,
the fourth line references the dependencies. The particular versions will be
the ones defined by the nixpkgs-channel from the given revision in -I
.
The beauty of this approach is that one could also do it with perl or python scripts, pulling their dependencies (as long as they are in nixpkgs).