A set of tools to make integration between Elixir Mix projects and Nix smooth.
This is especially useful for creating packages using nothing but MixNix and the
mix.lock
found in almost all Elixir projects.
It's primarily meant for packaging applications for deployment, like servers or
executables, for normal development I'd still recommend a mix
based workflow.
This project is still in early development, so I'm looking for people who can try and run this on their projects and report any issues that might arise.
You can run nix-build
and use the ./result/bin/mixnix
executable.
Temporarily install into your user profile via nix-env -i ./result
. Adding
this to nixpkgs is one of the future objectives, but not a high priority right
now until it's generally proven more useful.
A good starting point is taking a look at the derivations in
./nix/test/passing
. Which contains examples of some projects I got to build so
far.
If a project doesn't have any dependencies, building it is very straightforward. As an example we'll use tty2048.
mix2nix.mkMixPackage {
name = "tty2048";
version = "0.0.1";
src = fetchGit {
url = https://github.com/lexmag/tty2048;
rev = "f800247354593929b653f9f947a7c6f1844ad9fe";
};
releaseType = "escript";
}
The easiest way mixnix
can work is by using its derivation, and passing it a
mix.lock
file to process on the fly.
This usually looks like:
The conventional method of making executable Elixir applications is to use the escript.build
mix task.
mix2nix.mkMixPackage {
name = "mixnix";
version = "0.0.1";
src = ./.;
mixLock = ./mix.lock;
releaseType = "escript";
}
This is required to build in more restricted environments that prevent
import-from-derivation
like default Hydra
installations or the nixpkgs repository.
This is usually done to avoid the significant performance impact of IFD in large
derivations.
To use mixnix
to generate a lockfile that can be imported directly into Nix,
you can execute it like this in the root directory of your project:
mixnix > mix.nix
MixNix will create a file describing all the dependencies needed to build the
project, mostly a mirrored version of the mix.lock
file but without converting
it on the fly.
mix2nix.mkMixPackage {
name = "mixnix";
version = "0.0.1";
src = ./.;
mixNix = ./mix.nix;
releaseType = "escript";
}
The only difference is that instead of mixLock = ./mix.lock
we're now using mixNix = ./mix.nix
.
The name and location of the file doesn't matter.
For development, I'd recommend simply starting the nix-shell
with the
shell.nix
in this repository. It'll make elixir
available in your
environment, and you can just run mix deps.get
and mix escript.build
to get
the mixnix
executable.
To run the Elixir tests, you can run the mix test
or mix test.watch
tasks.
A Nix test suite is still work in progress, for the moment there's a few
derivations in the nix/test
directory, with failing and passing derivations
that might also make nice examples if you want to know how to use MixNix for
your own project and what might go wrong.
You can run specific tests like this:
nix-build ./nix/test/all.nix -A passing.captain-fact-api
.
My primary objective for MixNix was to make developing and deploying Elixir applications on NixOS one simple step. It's not fully-featured and may break with certain dependencies that I haven't had the chance to test it with yet.
But the core idea was simple. Given that the mix.lock
file already contains
checksums of each package, what would be the most straightforward way to teach
Nix about how to fetch them.
Turns out that the hashing algorithm is well described in the
hex.pm specification.
So the solution was to first fetch the tarball, then create a file that contains
the contents the hash describes, and in the build step extract only the gzipped
tarball from it, which took a bit of fiddling with dd
but ended up working
just fine for us.
If someone comes up with a more elegant solution with less steps, I'd very much appreciate a PR :)
- hex2nix
- It was used to generate all the
beamPackages
that are found innixpkgs
. It has the tiny drawback that it downloads all of the availablehex.pm
packages which takes hours and may fail at any point. - Consequently the
beamPackages
collection hasn't been updated since March 2018, making building any current project with it impossible. - It also doesn't support git dependencies or alternative repositories.
- It was used to generate all the