Mathias Polligkeit
  • Dev
  • Impro
  • Sheet Music
  • Contact
Sep 18, 2022

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)
  • elixir
  • nix

See Also

  • Elixir Dev Environment With Nix
  • Announcing LetMe
  • Zanzibar Goes Elixir, Pt. 2: Read API
  • Zanzibar Goes Elixir, Pt. 1: Setup and Relation Tuples
  • Essential Elixir Resources
  • privacy policy