Skip to content

Instantly share code, notes, and snippets.

@jbhoot
Last active June 24, 2021 12:25
Show Gist options
  • Save jbhoot/d8edf6b14603e0a0a2626196e96c6257 to your computer and use it in GitHub Desktop.
Save jbhoot/d8edf6b14603e0a0a2626196e96c6257 to your computer and use it in GitHub Desktop.
An overview of Nix for a beginner

Disclaimer

I consider myself still at the end of the beginner phase, having barely scratched the surface. Everything below is my understanding of the Nix ecosystem. Parts of it might be incorrect or at least not pedantic.

My environment

I run nix on a non-M1 mac. My experience has been smooth, once you execute the necessary mac-specific command to allow nix-store to be installed at /nix/store (explained in the official manual.). I don't know what complexities M1 brings in.

I also run nixos on a thinkpad. nixos works very well on the happy paths (and most of the paths are happy paths). But as soon as you require a package that's not in nixpkgs, or then you have to dive deep inside the whole ecosystem. I am in the process of figuring out a few packages. For example, merlin does not provide the necessary files to vim. But I'm sold on the idea of declarative package and configuration management, so much so that I am planning to deploy nixos on my personal server when time permits.

Too many Nix-es

A small primer if you aren't well-versed with the nix terminology at all. Personally I think they have messed up the naming. There are a number of nixes involved:

  1. Nix Expression Language. The ecosystem uses a small, dynamic, pure, functional language to describe expressions. And expression is the smallest unit in the next language. These are composed to form derivations.

  2. A nix derivation is a nix expression that describes a package, "executing" which builds the described package.

  3. nixpkgs - the official collection of nix derivations/packages. Note that this repository only contains the derivations. It is accompanied by a cache of binaries, corresponding to the derivations. When you install a package from nixpkgs, you are essentially downloading a cached binary. Not all derivations in nixpkgs have a corresponding binary in the cache (kmousetool for example).

  4. Nix package manager lets you install, build, and customize nix derivations.

  5. Several nix-* commands accompany the Nix package manager.

  6. nix channel defines the version of the set of packages the nix package manager is pointing to.

  7. NixOS, which is basically the sum of the Nix package manager and a specific set of derivations from nixpkgs to describe the OS configuration and modules. Simply speaking, nixos is basically the nix community dogfooding. Keep in mind that on nixos, you have to do everything the next way. If nixpkgs doesnt provide a package you absolutely require, then I would recommend staying away from nixos unless you have tons of time at hand, and until you have learned to build packages the nix way.

  8. home-manager, an unofficial but popular tool allows declarative configuration of packages and dotfiles at user-level. It builds on top of nix package manager and nixpkgs.

Where to dig?

Stick to the official sources.

There are variations even here:

  1. nix pills. Often considered as the entry point. Personally I found them unsatisfactory and out of date. For example, they recommend the deprecated way of overrides instead of overlays to manage custom packages.

  2. nixos.wiki - A few gems here and there, but certainly not your starting point.

  3. nix.dev - A few gems here and there, but certainly not your starting point.

  4. manuals. I found them the best go-to source.

  5. Man pages of nix-* commands. An absolutely essential reference.

  6. home-manager manual, also accessible by man home-configuration.nix, once home manager is installed.

To start with, do not touch anything but the official manuals, man pages, and the home-manager manual (man home-configuration.nix).

There is a structure and an order to the manuals.

  1. nix (https://nixos.org/manual/nix/stable/): explains the nix package manager as well as the nix expression language. It explains the installation (including the macos complications) and usage of nix. It also teaches how to write your first nix expression and build it into a package.

  2. nixpkgs (https://nixos.org/manual/nixos/stable/): primarily describes how to write packages for the Nix Packages collection (Nixpkgs). Thus it’s mainly for packagers and developers who want to add packages to Nixpkgs

  3. nixos (https://nixos.org/manual/nixos/stable/index.html) deals with nixos-specific aspects of the nix ecosystem.

  4. home-manager manual: home-manager, while not an official part of nix, is essential. You use it to build a user-level, declarative package and configuration management.

How to begin?

  1. Get familiar with the nix expression language.

    You will need to start fiddling with expressions as soon as you are a few steps in.

    The official manual covers it within a section: https://nixos.org/manual/nix/unstable/expressions/expression-language.html

  2. Get familiar with the package manager.

    Get a high-level overview and feel of nix package manager.

    Start out small. I recommend getting familiar with the nix package manager by replacing a few of your day-to-day command-line utilities. By replacing, I mean uninstalling the stock/homebrew utility, and installing it using the next package manager. Do not keep both.

    Nix provides an imperative and a declarative way to manage packages and configuration. Imperative approach is built around nix-env. Declarative approach is best handled with home-manager.

    nix-env is best seen as a transitory tool that provides you a fleeting familiarity with other Linux package managers and homebrew. You are not expected to stick with it. Personally I used nix-env only for a couple of days, then switched to home-manager. I haven’t touched it since.

    I recommend going full declarative with home-manager.

  3. Learn home-manager.

    Use home-manager to describe your user-level package-set and configurations (zshrc, bashrc, vimrc, font configuration, symlinking config ando other files to their appropriate places, what not).

  4. Build your own isolated development environments.

    nix-shell to create and manage isolated environment. This utility is key to the ability of next to provide what utilities like virtualenv provides - Isolated, per project environment, regardless of the programming language and technologies involved.

    nix-shell lets you enter into a defined shell environment, implicitly defined by a default.nix or shell.nix in the current folder, or a nix expression explicitly passed to nix-shell

  5. Build your own packages and manage them with overlays.

    nix-build lets you build a package from a nix derivation. This part is where you will deal with nitty-gritties like overriding an nixpkgs derivation, writing shell hooks, etc.

    An overlay is a set of custom derivations which can describe overridden derivations from nixpkgs and/or entirely new derivations. The overlay section in nixpkgs manual covers everything you need.

Basically, you will use home-manager to declare the packages you want to install, and declare and link configuration files. You will use nix to define, build, and maintain custom packages, custom shell and development environments. Both of them use nix expression language and shell commands to do their job.

.nix files

  • default.nix: Commands like nix-shell and nix-build look for this file automatically in the current directory, and treats it as the entry point. If you want to understand someone else's set of nix expressions, start with their default.nix file.

  • shell.nix: If default.nix is not found, then nix-shell looks for this file next to begin each job.

Up and coming

The whole ecosystem is undergoing a churn.

nix-* to nix

Work is ongoing to integrate all of the nix-* commands into a single interface - nix command (yet another nix!). So:

  • nix-build becomes nix
  • nix-shell becomes nix run

In fact, even right now, all of the nix-* commands actually point to a single nix binary underneath:

>> which nix-shell | xargs ls -la
lrwxr-xr-x  1 jayesh  admin  68 Jan  1  1970 /Users/jayesh/.nix-profile/bin/nix-shell -> /nix/store/8c98r6zlwn2d40qm7jnnrr2rdlqviszr-nix-2.3.10/bin/nix-shell

>> ls -la /nix/store/8c98r6zlwn2d40qm7jnnrr2rdlqviszr-nix-2.3.10/bin/nix-shell
lrwxr-xr-x  1 jayesh  staff  3 Jan  1  1970 /nix/store/8c98r6zlwn2d40qm7jnnrr2rdlqviszr-nix-2.3.10/bin/nix-shell -> nix

>> which nix
/Users/jayesh/.nix-profile/bin/nix

I recommend sticking to the nix-* commands for now, because not all the features have been translated yet. Also, only documentation is the nix manual. No man page for nix.

What the Flakes?

From my cursory understanding, they are a replacement of nix-channels. That’s all I know. I’m not interested right now. I’m sure I will transition my setup to it when the time comes (when it becomes the official way). I would recommend the beginners to do the same.

Parting note

Don’t get too frustrated with technical terms like ‘fixed point’. Make the best of your understanding from the surrounding context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment