This document is targeted at those who seek to build reproducible dev environment across machines, OS, and time.
It maybe easier for remote teams to work together and not spending hours each person setting up asdf/pyenv/rbenv
, LSP servers
, linters
, runtime/libs
. Nix is probably the closest thing to Docker in terms of development environment.
Flake is used here because it provides hermetic build, with absolutely no reliance on system environment (be it Arch/Catalina/Mojave). Also it freezes dependencies in flake.lock
so builds are reproducible.
This gist provides the setup to develop Java/Clojure/Python applications on Nix. But it can be easily adapted to ruby, nodejs, haskell.
https://nixos.org/guides/install-nix.html
No assumption is made whether you are using home-manager, configuration.nix. I don't use those because I am not pure enough :p
You just need to know:
In summary:
nix-env
is like homebrew, eg.nix-env -iA nixpkgs.nixfmt
nix-build
turns derivation into binary. (think of it asmake
)nix-shell
ornix develop
allows you go enter a shell with the build environent
Nix packages can be found at https://search.nixos.org/packages
Initially, I have mistaken the Nix channel (eg. nix-channel --add https://nixos.org/channels/nixpkgs-unstable
) as the same as the Nix package (nix-env -f '<nixpkgs> -q nix'
). They are not the same, the former determines the version/recency of packages, while the latter is a CLI.
# At the time of writing, they are equivalent, just run either 1 of them:
nix-env -iA nixpkgs.nixFlakes # do this,
nix-env -iA nixpkgs.nixUnstable # or this
Modify ~/.config/nix/nix.conf
with
You might see ca-references
in other people's nix.conf, and that is for running nix profile list|add|remove
, which is out of the scope of this guide.
experimental-features = nix-command flakes
keep-derivations = true
keep-outputs = true
keep-*
is used by nix-direnv
in the next section
To use flake, simply create flake.nix
in the project root.
Flakes are self-contained units that have inputs (dependencies) and outputs (packages, deployment instructions, Nix functions for use in other flakes)
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs";
};
outputs = { self, nixpkgs }: {
packages.x86_64-linux.hello = /* something here */;
};
}
You can use various input format in flake (and that is a power I like)
{
# github example, also supported gitlab:
inputs.nixpkgs.url = "github:Mic92/nixpkgs/master";
# git urls
inputs.git-example.url = "git+https://git.somehost.tld/user/path";
# local directories (for absolute paths you can omit 'path:')
inputs.directory-example.url = "path:/path/to/repo";
# Use this for non-flakes
inputs.bar.url = "github:foo/bar/branch";
inputs.bar.flake = false;
# Overwrite inputs in a flake
# This is useful to use the same nixpkgs version in both flakes
inputs.sops-nix.url = "github:Mic92/sops-nix";
inputs.sops-nix.inputs.nixpkgs.follows = "nixpkgs";
# Pin flakes to a specific revision
inputs.nix-doom-emacs.url = "github:vlaci/nix-doom-emacs?rev=238b18d7b2c8239f676358634bfb32693d3706f3";
inputs.nix-doom-emacs.flake = false;
}
Direnv does not depend on Nix at all, install it from official website https://direnv.net.
Even without Nix, Direnv is pretty useful on its own. I use it with Doom emacs (https://github.com/hlissner/doom-emacs/tree/develop/modules/tools/direnv)
Do this for the first time:
git clone https://github.com/nix-community/nix-direnv $HOME/nix-direnv
# then, put this in ~/.direnvrc
# to source nix-direnv into .direnv
echo "source $HOME/nix-direnv/direnvrc" >> ~/.direnvrc