elm2nix 0.1

Our frontend is written in Elm and our deployments are done with Nix.

There are many benefits to using Nix for packaging: like reproducible installation with binaries, being able to diff for changes, rollback support, etc, with a single generic tool.

We benefit most once the whole deployment is Nixified, which is what we’ve done to our frontend in last December.


Back in November 2016 I’ve written down some ideas on how elm2nix could work. In December 2017 the first prototype of elm2nix was born, but it required a fork of the Elm compiler to gathering your project’s dependencies. Elm 0.19 came out with pinning for all dependencies, making it feasible for other packaging software to build Elm projects.

Installation and usage

Today we’re releasing elm2nix 0.1 and it’s already available in nixpkgs unstable and stable channels. The easiest way to install it is:

# install Nix
$ curl https://nixos.org/nix/install | sh

# activate Nix environment
$ source ~/.nix-profile/etc/profile.d/nix.sh

# install elm2nix binary
$ nix-env -i elm2nix

Given your current directory with an Elm 0.19 project, here are three commands to get Elm project build with Nix.

First, we need to generate a Nix file with metadata about dependencies:

$ elm2nix convert > elm-srcs.nix

Second, since Elm 0.19 packaging maintains a snapshot of http://package.elm-lang.org

$ elm2nix snapshot > versions.dat

And last, we generate a Nix expression by template, which ties everything together:

$ elm2nix init > default.nix

By default, the template will use just plain elm-make to compile your project.

To build using Nix and see the generated output in Chromium:

$ nix-build
$ chromium ./result/Main.html

What could be improved in Elm

You may notice that elm2nix convert output includes sha256 hashes. Nix will require hashes for anything that’s fetched from the internet. Elm package index does provide an endpoint with hashes, but then Nix needs to know what’s the hash of the endpoint response.

To address this issue it would be ideal if there would be elm.lock file or similar with all dependencies pinned including their hashes - then Nix would have everything available locally. Other package managers for various languages are slowly going towards outputing metadata file that explains the whole build process. This can be considered an API between build planning and the actual builder.

Another minor issue comes from versions.dat. Ideally instead of committing to git repository a few megabytes of serialized JSON, one would be able to point to an url that would present binary file pinned at some specific time - allowing it to always be verifiable with upfront known hash.

What could be improved in Nix

Nix expression generated by elm2nix init could be upstreamed to nixpkgs or another Nix repository. This would allow for small footprint in an application and stable documentation.

Default expression might not be enough for everyone, as you can use Parcel, Webpack or any other asset management tool for building the project. There’s room for all common environments.

Closing thoughts

Stay tuned for another post on how to develop Elm applications with Parcel and Nix.

Since you’re here, we’re building next-generation CI and binary caching services, take a look at Hercules CI and Cachix.