loading...

Nix, the shell bootstrapper

itshaydendev profile image Hayden Young Updated on ・3 min read

So recently I swapped out Arch Linux for NixOS, mainly because I could bootstrap my entire PC with a configuration file. I never really looked into nix as a tool until today. Of course, I've been using nix as a package manager for about a month due to NixOS, but I'd never looked into nix itself for development purposes. And oh boy, was I glad that I did. And here's why.


with import <nixpkgs> {};

stdenv.mkDerivation {
  name = "node";
  buildInputs = [
    nodejs
  ];
  shellHook = ''
    export PATH="$PWD/node_modules/.bin/:$PATH"

    alias run='npm run'
  '';
}

So what the fork is this?! Well, calm down a little and I'll tell you.

This beautiful piece of functional code you see before you is a Nix Derivation. It's used in this instance to make a complete dev environment for me for nodejs. It lives in a file called default.nix, and allows for anyone to just come along and run nix-shell and have a full Node.js development environment complete with an alias of npm run to run.

The fact that I can do this without having to go download NVM or nodenv or similar is... Well, let's just be calm and say it saves me a lot of headaches.

So let's break that file down.


with import <nixpkgs> {};

This tells Nix to import the nixpkgs package registry, which is the official source for nix packages. This becomes important later.


stdenv.mkDerivation {
  # ...
}

Does what it says on the tin really. Makes a new nix derivation, defined & configured by the contents of the block. This is what Nix evaluates to produce our dev environment.


name = "node";

This just gives our derivation a name, duh. I've called it node here, but you could call it stopwritingpostsondevyoudontknowanything for all I care.


buildInputs = [
  nodejs
];

This is where that nixpkgs import line comes in handy. This is telling Nix to install the latest LTS version (at least the current LTS version recorded in the nixpkgs repo) of Node.js, and make it available to us in the dev environment. You could add anything here. Need to build native extensions? Throw gcc and automake in here!


shellHook = ''
  export PATH="$PWD/node_modules/.bin/:$PATH"

  alias run='npm run'
'';

So this is essentially a bash script that will be called when the environment is created. In this instance, it's adding the node_modules/.bin directory to our PATH variable, so we can call any NPM-installed binaries as if they were globally installed on our system. Really cool for those obscure linting commands you only ever need to run once or twice.

It also aliases npm run to run, allowing me to do run build instead of npm run build. Tiny amount of time saved, but I love tiny, insignificant time saving measures.


So that's the default.nix file covered.

But Hayden, you keep telling me how cool and epic and amazing and <insert other synonym for 'cool' here>, but you haven't shown me anything yet.

no talk me, i angy.

Well, don't be so angy. You want a demo putting it all together? Have one.

asciinema

See? It's fantastic.

Well, that about wraps this up.

TL;DR, Nix is brilliant and you should try it out now. Go. Leave the room please. Go. I don't want you around anymore. Go try Nix. Now. BYE!

Posted on by:

itshaydendev profile

Hayden Young

@itshaydendev

I'm a full-stack developer adept in JavaScript/TypeScript and React, learning Go and C# on the side. My work is in PHP currently, though.

Discussion

pic
Editor guide