Elixir Dev Environment With Nix Flakes
In a previous article, I described how to set use Nix and Niv to configure an Elixir dev environment. This setup can be simplified by using Nix flakes instead of Niv.
At the time of writing, Nix flakes are still an experimental feature. If you follow the stable Nix channel, you may need to enable the feature first.
Initialize flake
You can initialize a flake by running:
nix flake init
This will create a flake.nix
file in the current directory.
Inputs
Add this to the generated file.
inputs = {
nixpkgs = { url = "github:NixOS/nixpkgs/nixos-22.05"; };
flake-utils = { url = "github:numtide/flake-utils"; };
};
Here we define nixos-22.05
as package source. You could use
nixpkgs-unstable
instead. We also add
flake-utils, which defines a couple
of convenience functions for writing flakes.
Outputs
Next, define the dev shell within the outputs.
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
elixir = pkgs.beam.packages.erlang.elixir;
in
with pkgs;
{
devShell = pkgs.mkShell {
buildInputs = [
elixir
glibcLocales
];
};
});
To override the Elixir version, replace elixir = pkgs.beam.packages.erlang.elixir
with:
beamPkg = pkgs.beam.packagesWith pkgs.erlangR25;
elixir = beamPkg.elixir.override {
version = "1.14.0";
sha256 = "NJQ2unK7AeLGfaW/hVXm7yroweEfudKVUa216RUmLJs=";
};
When you update the Elixir version, make sure to update the sha256 value as
well. You can find it in the terminal output by replacing the previous hash with
pkgs.lib.fakeSha256
.
If you also need to override the Erlang version, you can do something like this:
erlang = pkgs.erlangR25.override {
version = "26.0";
sha256 = pkgs.lib.fakeSha256;
};
beamPkg = pkgs.beam.packagesWith erlang;
This is just an example, there is no OTP 26 at the time of writing.
You probably will need more build inputs. For example, you may want to add
postgresql
in order to use psql
and pg_dump
, you may need nodejs-16_x
to build the frontend assets, you may need to add chromedriver
to run
tests with Wallaby, or you may need
imagemagick
for image processing. Whatever you need, just add it to the
buildInputs
of the devShell
. You can search for packages with:
nix search nixpkgs postgres
The previous article also mentioned packages like inotify-tools
,
terminal-notifier
, CoreFoundation
and CoreServices
. I didn’t have any
issues without specifying them, but in case you run into trouble, refer back to
the original article to see how to
install them depending on the system.
Direnv
We used direnv to load the dev environment automatically
when changing the directory to the project folder. We can still do that with
flakes, but instead of use_nix
, we use flake
.
echo "use flake" > .envrc
If you are setting up a new project, don’t forget to add .direnv
to your
.gitignore
file.
echo ".direnv/" >> .gitignore
You’ll need to run direnv allow
once.
direnv allow
If you make changes to the flake, you can reload the environment with:
direnv reload
Updating packages
When you load the environment the first time, a flake.lock
file is created,
which you should commit. You can later update the packages with:
nix flake update --commit-lock-file
What else?
This setup only configures a dev shell environment. You could expand on this and build the application binary with Nix as well. You could even configure a docker image using Nix. I might get back to this in a future article.
Resources
- Flakes documentation
- Getting Started Using Nix Flakes as an Elixir Development Environment
- Rust Environment and Docker Build With Nix Flakes
- Practical Nix Flakes
- Nix Flakes: An Introduction
- Nix Flakes: Packages and How to Use Them
- BEAM languages (Nix docs)