Nix Quickstart

Nix seems to stump a lot of newcomers. I had a few failed starts at trying at Nix myself, but I now find myself at a happy amount of knowledge where Nix is more helpful than hurtful.

How I think of Nix

Most likely, you’ve worked with one of the following before:

Example package.json

  "name": "example",
  "version": "1.0.0",
  "devDependencies": {
    "ts-node": "^10.5.0",
  "dependencies": {
    "react": "18.2.0"

All of these attempt to define a project’s dependencies for that particular language. We like these files because it means that a new computer can quickly and correctly install all the required language-specific dependencies, assuming they have the language (compiler, interpreter..) and/or package manager installed. Here, we are attempting to create a deterministic environment.

So let’s take it up a level. Wouldn’t it be nice if we could not only define the language-specific dependencies, but just also the language / binaries in general? That’s where Nix comes in. Here’s an example shell.nix file:

with import <nixpkgs> { };

pkgs.mkShell {
  buildInputs = [
  shellHook = ''
    alias i='yarn'
    alias s='yarn start'

Running nix-shell will start a new shell with nodejs and yarn installed (try which nodejs or which yarn). It will also load the aliases i and s that you can use in this new shell.

How I use nix

Very basics, install Nix.

I like to add this global alias for convenience

alias ns='nix-shell'

For each project, I define a shell.nix file in the root directory with the dependencies I need. You can easily find available packages on Nix search which I keep bookmarked.

Finally, I call ns when I am in a project. I use ctrl+D or exit to leave the Nix shell and return to my default shell.

Why I like this setup

The biggest is that it makes multi-computer dev a lot less painful. The only software I need to install on any computer I own is Nix. It also helps that most of the time, Nix works the same way on Linux as it does on MacOS.

The more obvious one is that I have relatively deterministic setups for all my projects. Storing aliases in my shell.nix also means I can record the common commands that need to be run on any project.