You have installed Nix. Now let’s play with the nix
command but without bothering to write any Nix expressions yet (we reserve that for the next tutorial). In particular, we will learn how to use packages from the nixpkgs repository and elsewhere.
Running a package
As of this writing, nixpkgs has over 80,000 packages. You can search them here. Search for “cowsay
” and you will find that it is available in Nixpkgs. We can download and run the cowsay package as follows:
$ nix run nixpkgs#cowsay "G'day $USER"
____________
< G'day srid >
------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
$
nix run
nix run
command will run the specified package from the flake. Here nixpkgs
is the flake, followed by the letter #
, which is followed by the package (Derivation) name cowsay
that is outputted by that flake. See Flake URL for details on the syntax.
Looking inside a package
What is a Nix “package”? Technically, a Nix package is a special Store path built using instructions from a Derivation, both of which reside in the Nix Store. To see what is contained by the cowsay
package, look inside its Store path. To get the store path for a package (here, cowsay
), run nix build
as follows:
$ nix build nixpkgs#cowsay --no-link --print-out-paths
/nix/store/8ij2wj5nh4faqwqjy1fqg20llawbi0d5-cowsay-3.7.0-man
/nix/store/n1lnrvgl43k6zln1s5wxcp2zh9bm0z63-cowsay-3.7.0
The cowsay
Derivation produces two output paths, the second of which is the cowsay binary package (the first one is the separate documentation path), and if you inspect that
1
you will see the contents of it:
$ nix run nixpkgs#tree /nix/store/n1lnrvgl43k6zln1s5wxcp2zh9bm0z63-cowsay-3.7.0
/nix/store/n1lnrvgl43k6zln1s5wxcp2zh9bm0z63-cowsay-3.7.0
├── bin
│ ├── cowsay
│ └── cowthink -> cowsay
└── share
└── cowsay
├── cows
│ ├── DragonAndCow.pm
│ ├── Example.pm
│ ├── Frogs.pm
│ ├── ...
/nix/store
is a special directory representing the Nix Store. The paths inside /nix/store
are known as Store path. Nix fundamentally is, in large part, about manipulating these store paths in a pure and reproducible fashion; Derivation are “recipes” that does this manipulation, and they too live in the Nix Store.
Shell environment
One of the powers of Nix is that it enables us to create isolated shell environments containing just the packages we need. For eg., here’s how we create a transient shell containing the “cowsay” and “fortune” packages:
$ nix shell nixpkgs#cowsay nixpkgs#fortune
❯
From here, you can verify that both the programs are indeed in $PATH
as indicated by the “bin” directory in their respective store paths:
$ nix shell nixpkgs#cowsay nixpkgs#fortune
❯ which cowsay
/nix/store/n1lnrvgl43k6zln1s5wxcp2zh9bm0z63-cowsay-3.7.0/bin/cowsay
❯ which fortune
/nix/store/mfw77f008xy0zb7dqdyggw0xj2gd4jjv-fortune-mod-3.20.0/bin/fortune
❯ fortune | cowsay
________________________________
/ The longer the title, the less \
\ important the job. /
--------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Instead of creating a shell environment, you can also run commands one-off using the -c
option. The above session can equally be achieved using:
nix shell nixpkgs#cowsay nixpkgs#fortune -c sh -c 'fortune | cowsay'
Installing a package
This section explains how to install a package imperatively. For a better way of installing packages (declaratively), see home-manager.
Neither nix run
nor nix shell
will mutate your system environment, aside from changing the Nix Store. If you would like to permanently install a package somewhere under your $HOME directory, you can do so using nix profile install
:
$ nix profile install nixpkgs#cowsay nixpkgs#fortune
$ which cowsay
/home/user/.nix-profile/bin/cowsay
$ which fortune
/home/user/.nix-profile/bin/fortune
$
nix profile install
installs symlinks under the $HOME/.nix-profile
directory, which the Nix installer already added to your $PATH
. For details, see the Nix manual.
These symlinks, ultimately, point to the package Store path outputs under the Nix Store, viz.:
$ readlink $(which fortune)
/nix/store/mfw77f008xy0zb7dqdyggw0xj2gd4jjv-fortune-mod-3.20.0/bin/fortune
Note that this is the same path used by both nix build
and nix shell
. Each specific package is uniquely identified by their Store path; changing any part of its build recipe (including dependencies), changes that path. Hence, nix is reproducible.
How is nixpkgs fetched
So far we have been retrieving and installing software from the nixpkgs flake, which is defined in the GitHub repository: https://github.com/nixos/nixpkgs. This information comes from the Flake registry:
$ nix registry list | grep nixpkgs
global flake:nixpkgs github:NixOS/nixpkgs/nixpkgs-unstable
A registry is simply a mapping of flake alias to Flake URL.
We can find the current Git revision of nixpkgs used by our registry as follows:
❯ nix flake metadata nixpkgs --json | nix run nixpkgs#jq -- -r .locked.rev
317484b1ead87b9c1b8ac5261a8d2dd748a0492d
From here, you can see the revision on GitHub.
The discerning readers may have noticed that the registry specifies only the branch (nixpkgs-unstable
), but not the specific revision. Nix registry internally caches flakes locally and updates them automatically, thus the specific Git revision of nixpkgs used may change over time!
To avoid the aforementioned automatic update, you can manually pin the registry entry for nixpkgs. In home-manager, we will see an automatic and declarative way of doing this (through flake inputs).
You are not required to use a registry. Without a registry, getting a package off nixpkgs would instead involve its fully qualified URL:
$ nix run github:NixOS/nixpkgs/nixpkgs-unstable#cowsay
...
Using software outside of nixpkgs
nixpkgs is not the only way to get software packaged by Nix. As you have seen immediately above, you can install programs from any flake by specifying its flake URL to the nix ?
commands. For example, Emanote (which is used to build this very website) can be executed or installed directly off its flake on GitHub:
$ nix run github:srid/emanote
...
You can of course also install it to your home directory:
$ nix profile install github:srid/emanote
...
What’s next
- See Rapid Introduction to Nix where we will go over writing simple Nix expressions and flakes.
- If you want to manage your system using Nix, see home-manager Tutorial Series (if you are on macOS or non-NixOS Linux) or NixOS Tutorial Series (if you are on NixOS).