DEV Community


Posted on • Originally published at on

nix report

This article is created as a record of the feedback of the usage of nix, also stand for learning how to use nix in daily developing life. Remember I would not dig into the implementation or model concept inside of nix but all about how to use it to improve the developing environment.


To install nix all you have to do is running: sh <(curl --no-daemon and follow the content, provided by the script after the script installed process down, on Linux or macOS.

To avoid outdated information, here is the single-user installation(which you do above), and the multi-user installation.


After installation, you would get several different commands for different purposes. I would introduce them one by one(only for those I’m using).


nix-env is like brew for MacOS, apt-get for Ubuntu, yum for CentOS, but for all platform with nix. This command is the first one command would help immediately. You can do: nix-env -i go or nix-env --install go, after that let’s check the binary go by which go, is located at $HOME/.nix-profile/bin/go. You can also use different channel(package source) for self-deployed packages or any other is not provided by nix channel.

Use nix-env --help to get more information


nix-shell would read shell.nix or fallback to read default.nix these config files. To understand what we do in it we need an example:

  pkgs = import <nixpkgs> { };
  inherit (pkgs) mkShell;
  inherit (pkgs) haskellPackages;
  inherit (haskellPackages) cabal-install;
  inherit (haskellPackages) stylish-haskell;

  ghc = haskellPackages.ghcWithPackages (pkgs: with pkgs; [base mtl]);
mkShell {
  buildInputs = [

Enter fullscreen mode Exit fullscreen mode

mkShell would return a shell by its argument set: {}, at here we can take a look at stylish-haskell this Haskell formatter, in nix-shell environment type which stylish-haskell would get /nix/store/qqj9ldclapfbxhnvb357mjy5d5rjg6ip-stylish-haskell-, and if you quit the environment should won’t have the binary.


Now, we already introduce the global level installer and project level installer. We have to go into how to create your own package.

nix-build would read default.nix to use its value as your package. Let’s take a look at what it means.

  pkgs = import <nixpkgs> { };

  dependencies = import ./deps.nix;
  pkgs.haskellPackages.callPackage ./little-scheme.nix { dependencies=dependencies; }

Enter fullscreen mode Exit fullscreen mode

Ignore deps.nix, that’s a list has all Haskell dependencies I used.

pkgs.haskellPackages.callPackage creates a haskell package via it’s argument. Let’s dig into what little-scheme.nix do:

{ mkDerivation, base, mtl, dependencies, stdenv }:
mkDerivation {
  pname = "little-scheme";
  version = "0.1.0";
  src = stdenv.lib.sourceFilesBySuffices ./. [".hs" ".cabal" "LICENSE"];
  isLibrary = false;
  isExecutable = true;
  executableHaskellDepends = [base mtl] ++ dependencies;
  license =;

Enter fullscreen mode Exit fullscreen mode

src be set to stdenv.lib.sourceFilesBySuffices ./. [".hs" ".cabal" "LICENSE"], this line means only .hs, .cabal and LICENSE would lead a new build.

executableHaskellDepends would take a list of Haskell libraries.

{}: expression is a function. {} use pattern matching to extract the value from input set. a: c is take a return c, a: b: c is take a return b: c, consider to read lambda calculus to understand the function in nix.

Advanced use case


direnv is a powerful shell environment extension, it loads or unloads an environment depending on the current directory. To install it we can execute nix-env --install direnv, then add eval "$(direnv hook zsh)" at the end of $HOME/.zshrc(for others shells).

direnv supports using nix as environment configuration, you can put use_nix in the $dir/.envrc, and it would watch $dir/shell.nix and $dir/default.nix to update the environment. However, the current version use_nix has cache missing issue, so you can just copy whole content from, and put use_nix -s shell.nix in the $dir/.envrc.

p.s. A minor issue is direnv do not work with alias, so probably still have to use $HOME/.zshrc to manage them.

Top comments (0)