using nix to manage your dev-env
I use Nix to manage dev/build dependencies.
With it, I can declaratively ensure that dev/build dependencies for a project
(node, rustup, rustfmt etc) are automatically installed and available on any computer that I work on.
The tools are scoped to the project’s local nix-shell, so I can manage versions independently between projects.
I only install nix once when setting up my machine,
then when I cd into a project folder direnv runs nix to load the dependencies necessary for that project,
but you can also just run nix-shell
to start a shell with the dependencies loaded.
some things I like about it:
- In a team setting it can ensure that no-one needs any specialised instructions to configure their machine for local dev. Instead they just cd into the project, and they can already build and run it
- Packages can be pinned to a specific version
- It can be extended to CI build machine setup
- the config file is actually a script, where you can execute shell commands, and set up env vars as well
- there is a project called home-manager which allows you to use nix for declaratively managing your OS user level packages/applications as well
a simple setup
- install nix
- install direnv and install the shell hook
- in your project folder, create a
.envrc
file and add the textuse nix
. You will need to rundirenv allow
after creating this file. -
still in your project folder, create a
shell.nix
file, and add the following contents:{ pkgs ? import <nixpkgs> {} }; pkgs.mkShell { buildInputs = [] }
-
go to https://search.nixos.org and search for any packages you need to run/build your project.
For example, let’s add nodejs and pnpm.
- Searching for “nodejs” should yield the correct result in the first entry.
- Click on the name, select the tab titled “On non-NixOS” in the expanded block,
and referencing the code block,
copy the text
nixpkgs.nodejs
into thebuildInputs
list (note that you don’t need commas between items) and replacenixpkgs
withpkgs
- Following the same process with
pnpm
, you will notice that the package is namespaced tonodePackages
. This is fine, you should end up withpkgs.nodePackages.pnpm
in your buildInputs.
The file should now look like this:
{ pkgs ? import <nixpkgs> {} }; pkgs.mkShell { buildInputs = [ pkgs.nodejs pkgs.nodePackages.pnpm ] }
- pressing the
enter
key orcd
ing out and back into your project folder should now trigger an installation of the declared packages. When it’s done,which node
should print a path in/nix/store
(not sure if this will be the same under all OSes though). - You’re done now. You can finally rest and watch the sun rise on a grateful universe.
nb
- the “OS” part of the name “NixOS” is a reference to a linux distro that integrates deeply with the nix tool, but you don’t have to use the OS to try/use the tool.
- I found the website somewhat confusing when I first tried it, don’t be discouraged by this.
- here’s a base snippet I use when starting a new nix file.
- when using it with
direnv
, it takes a couple of seconds to load your shell when youcd
into the project. To solve this I use nix-direnv which caches the shell and dramatically speeds it up