Using niv to install recent Elixir in your nix-shell
May 24, 2021โข581 words
For the last few weeks I've been playing a bit with Nx - the new library for Numeric computation in Elixir.
Nx is still offered as a developer build and because of that it ends up having somewhat stringent requirements, in particular the latest version released a few days ago requires the most recent Erlang and Elixir.
The nix community does a great job at keeping the nixpkgs-unstable
channel up to date but Elixir 12 was not available yet.
Nudged by my friend Ben I decided to see what it would take to rely on community supported packages.
Finding an up-to-date Elixir derivation
To start, I did some googling. I looked for a community repository that offered up to date derivations for Elixir packages.
nix-beam is exactly what I needed. It exposes several derivations for BEAM (Erlang virtual machine).
To list them I ran the following command, as instructed in the README of nix-beam
.
$ nix-env -qaP -f https://github.com/jechol/nix-beam/archive/master.tar.gz
pkg.v23_3.elixir.v1_10_4 elixir-1.10.4_erlang-23.3
pkg.v23_3.elixir.v1_11_4 elixir-1.11.4_erlang-23.3
pkg.v23_3.elixir.v1_12_0 elixir-1.12.0_erlang-23.3
pkg.v24_0.elixir.v1_12_0 elixir-1.12.0_erlang-24.0
erlang.v23_3 erlang-23.3
erlang.v24_0 erlang-24.0
pkg.v23_3.rebar3 rebar3-3.15.1_erlang-23.3
pkg.v24_0.rebar3 rebar3-3.15.1_erlang-24.0
Using niv
to install Elixir
I then had to add nix-beam
as a source of derivations for my nix-shell.
In most of my nix-shell configurations I use niv.
niv
allows me to "pin" the version of nixpkgs
and also makes it easy to add other external dependencies.
$ nix-shell -p niv --run "niv init"
$ nix-shell -p niv --run "niv add jechol/nix-beam"
note that by default
niv init
will track the current nixpkgs-stable
Then I changed my shell.nix
to use the package sources generated by niv
.
# shell.nix
{ sources ? import ./nix/sources.nix }:
let
pkgs = import sources.nixpkgs { };
beam = import sources.nix-beam { };
inputs = [
...
pkgs.inotify-tools # example of nixpkgs package
beam.pkg.v24_0.elixir.v1_12_0 # package from the nix-beam repository
];
in
pkgs.mkShell {
buildInputs = inputs;
}
Add caching with Cachix
When I ran nix-shell
I noticed that after downloading some pre-built derivations a compilation process started. My laptop was about to build Erlang from source!
This is because packages from external sources are not part of the nixpkgs cache, nix-beam
only contains the derivation definition after all.
Thankfully the author of nix-beam
provides a hosted cache using cachix.
To use it and save a lot of compilation time first I had to install cachix
:
$ nix-env -iA cachix -f https://cachix.org/api/v1/install
and then add the provided cache for nix-beam
$ cachix use jechol
Then, I was able to run nix-shell
again and no compilation was required!
Note: if you use NixOS you might need to add your user as a
trustedUser
, that is required for thecachix use
part to work.
Conclusion
I hope this post helps you when you find yourself needing a dependency (Elixir or not) that is not available in the main package tree.
Notes:
Funny enough, the nixpkgs Pull Request mentioned at the beginning of this post was merged a few hours after I solved the issue and Elixir 12 is now in the nixpkgs-unstable
channel.
Because of that, a simpler solution would now be to add a niv
source to track unstable
and install Elixir using that source.
Also of note, most of the community maintained derivations do not offer caches in cachix
but often they also don't require a big build phase as the ones I was installing in this case.