Skip to content

Commit

Permalink
Convert code section to fenced, with the appropriate syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Noam Yorav-Raphael committed Apr 3, 2024
1 parent 4079785 commit 13c9916
Show file tree
Hide file tree
Showing 20 changed files with 1,419 additions and 1,039 deletions.
6 changes: 4 additions & 2 deletions pills/01-why-you-should-give-it-try.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ What we have is basically a store of all packages (with different versions occup

In fact, there's no ldconfig cache either. So where does bash find libc?

$ ldd `which bash`
libc.so.6 => /nix/store/94n64qy99ja0vgbkf675nyk39g9b978n-glibc-2.19/lib/libc.so.6 (0x00007f0248cce000)
```console
$ ldd `which bash`
libc.so.6 => /nix/store/94n64qy99ja0vgbkf675nyk39g9b978n-glibc-2.19/lib/libc.so.6 (0x00007f0248cce000)
```

It turns out that when bash was built, it was built against that specific version of glibc in the Nix store, and at runtime it will require exactly that glibc version.

Expand Down
24 changes: 16 additions & 8 deletions pills/02-install-on-your-running.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ Note: In a multi-user installation, such as the one used in NixOS, the store is

Start looking at the output of the install command:

copying Nix to /nix/store..........................
```
copying Nix to /nix/store..........................
```

That's the `/nix/store` we were talking about in the first article. We're copying in the necessary software to bootstrap a Nix system. You can see bash, coreutils, the C compiler toolchain, perl libraries, sqlite and Nix itself with its own tools and libnix.

Expand All @@ -32,7 +34,9 @@ You may have noticed that `/nix/store` can contain not only directories, but als

Right after copying the store, the installation process initializes a database:

initialising Nix database...
```
initialising Nix database...
```

Yes, Nix also has a database. It's stored under `/nix/var/nix/db`. It is a sqlite database that keeps track of the dependencies between derivations.

Expand Down Expand Up @@ -94,10 +98,12 @@ We'll talk about `manifest.nix` more in the next article.

More output from the installer:

downloading Nix expressions from `http://releases.nixos.org/nixpkgs/nixpkgs-14.10pre46060.a1a2851/nixexprs.tar.xz'...
unpacking channels...
created 2 symlinks in user environment
modifying /home/nix/.profile...
```
downloading Nix expressions from `http://releases.nixos.org/nixpkgs/nixpkgs-14.10pre46060.a1a2851/nixexprs.tar.xz'...
unpacking channels...
created 2 symlinks in user environment
modifying /home/nix/.profile...
```

Nix expressions are written in the [Nix language](https://nix.dev/tutorials/nix-language) and used to describe packages and how to build them. [Nixpkgs](https://nixos.org/nixpkgs/) is the repository containing all of the expressions: <https://github.com/NixOS/nixpkgs>.

Expand All @@ -119,8 +125,10 @@ You can, but there's a good reason to keep using `/nix` instead of a different d

You can see for yourself, don't worry if you see multiple bash derivations:

$ ldd /nix/store/*bash*/bin/bash
[...]
```console
$ ldd /nix/store/*bash*/bin/bash
[...]
```

Keeping the store in `/nix` means we can grab the binary cache from nixos.org (just like you grab packages from debian mirrors) otherwise:

Expand Down
130 changes: 81 additions & 49 deletions pills/03-enter-environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ In the previous article we created a Nix user, so let's start by switching to it

If that's not the case:

$ source ~/.nix-profile/etc/profile.d/nix.sh
```console
$ source ~/.nix-profile/etc/profile.d/nix.sh
```

To remind you, `~/.nix-profile/etc` points to the `nix-2.1.3` derivation. At this point, we are in our Nix user profile.

Expand All @@ -20,11 +22,13 @@ Finally something practical! Installation into the Nix environment is an interes

Back to the installation:

$ nix-env -i hello
installing 'hello-2.10'
[...]
building '/nix/store/0vqw0ssmh6y5zj48yg34gc6macr883xk-user-environment.drv'...
created 36 symlinks in user environment
```console
$ nix-env -i hello
installing 'hello-2.10'
[...]
building '/nix/store/0vqw0ssmh6y5zj48yg34gc6macr883xk-user-environment.drv'...
created 36 symlinks in user environment
```

Now you can run `hello`. Things to notice:

Expand All @@ -38,15 +42,19 @@ Now you can run `hello`. Things to notice:

We can list generations without walking through the `/nix` hierarchy:

$ nix-env --list-generations
1 2014-07-24 09:23:30
2 2014-07-25 08:45:01 (current)
```console
$ nix-env --list-generations
1 2014-07-24 09:23:30
2 2014-07-25 08:45:01 (current)
```

Listing installed derivations:

$ nix-env -q
nix-2.1.3
hello-2.10
```console
$ nix-env -q
nix-2.1.3
hello-2.10
```

So, where did `hello` really get installed? `which hello` is `~/.nix-profile/bin/hello` which points to the store. We can also list the derivation paths with `nix-env -q --out-path`. So that's what those derivation paths are called: the **output** of a build.

Expand All @@ -56,37 +64,45 @@ At this point you probably want to run `man` to get some documentation. Even if

Let's inspect the [profile](https://nixos.org/manual/nix/stable/package-management/profiles.html) a bit:

$ ls -l ~/.nix-profile/
dr-xr-xr-x 2 nix nix 4096 Jan 1 1970 bin
lrwxrwxrwx 1 nix nix 55 Jan 1 1970 etc -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/etc
[...]
```console
$ ls -l ~/.nix-profile/
dr-xr-xr-x 2 nix nix 4096 Jan 1 1970 bin
lrwxrwxrwx 1 nix nix 55 Jan 1 1970 etc -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/etc
[...]
```

Now that's interesting. When only `nix-2.1.3` was installed, `bin` was a symlink to `nix-2.1.3`. Now that we've actually installed some things (`man`, `hello`), it's a real directory, not a symlink.

$ ls -l ~/.nix-profile/bin/
[...]
man -> /nix/store/83cn9ing5sc6644h50dqzzfxcs07r2jn-man-1.6g/bin/man
[...]
nix-env -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env
[...]
hello -> /nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10/bin/hello
[...]
```console
$ ls -l ~/.nix-profile/bin/
[...]
man -> /nix/store/83cn9ing5sc6644h50dqzzfxcs07r2jn-man-1.6g/bin/man
[...]
nix-env -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env
[...]
hello -> /nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10/bin/hello
[...]
```

Okay, that's clearer now. `nix-env` merged the paths from the installed derivations. `which man` points to the Nix profile, rather than the system `man`, because `~/.nix-profile/bin` is at the head of `$PATH`.

## Rolling back and switching generation

The last command installed `man`. We should be at generation 3, unless you changed something in the middle. Let's say we want to rollback to the old generation:

$ nix-env --rollback
switching from generation 3 to 2
```console
$ nix-env --rollback
switching from generation 3 to 2
```

Now `nix-env -q` does not list `man` anymore. `` ls -l `which man` `` should now be your system copy.

Enough with the rollback, let's go back to the most recent generation:

$ nix-env -G 3
switching from generation 2 to 3
```console
$ nix-env -G 3
switching from generation 2 to 3
```

I invite you to read the manpage of `nix-env`. `nix-env` requires an operation to perform, then there are common options for all operations, as well as options specific to each operation.

Expand All @@ -100,20 +116,24 @@ To query and manipulate the store, there's the `nix-store` command. We can do so

To show the direct runtime dependencies of `hello`:

$ nix-store -q --references `which hello`
/nix/store/fg4yq8i8wd08xg3fy58l6q73cjy8hjr2-glibc-2.27
/nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10
```console
$ nix-store -q --references `which hello`
/nix/store/fg4yq8i8wd08xg3fy58l6q73cjy8hjr2-glibc-2.27
/nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10
```

The argument to `nix-store` can be anything as long as it points to the Nix store. It will follow symlinks.

It may not make sense to you right now, but let's print reverse dependencies of `hello`:

$ nix-store -q --referrers `which hello`
/nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10
/nix/store/fhvy2550cpmjgcjcx5rzz328i0kfv3z3-env-manifest.nix
/nix/store/yzdk0xvr0b8dcwhi2nns6d75k2ha5208-env-manifest.nix
/nix/store/mp987abm20c70pl8p31ljw1r5by4xwfw-user-environment
/nix/store/ppr3qbq7fk2m2pa49i2z3i32cvfhsv7p-user-environment
```console
$ nix-store -q --referrers `which hello`
/nix/store/58r35bqb4f3lxbnbabq718svq9i2pda3-hello-2.10
/nix/store/fhvy2550cpmjgcjcx5rzz328i0kfv3z3-env-manifest.nix
/nix/store/yzdk0xvr0b8dcwhi2nns6d75k2ha5208-env-manifest.nix
/nix/store/mp987abm20c70pl8p31ljw1r5by4xwfw-user-environment
/nix/store/ppr3qbq7fk2m2pa49i2z3i32cvfhsv7p-user-environment
```

Was it what you expected? It turns out that our environments depend upon `hello`. Yes, that means that the environments are in the store, and since they contain symlinks to `hello`, therefore the environment depends upon `hello`.

Expand All @@ -125,15 +145,19 @@ The `manifest.nix` file contains metadata about the environment, such as which d

The closures of a derivation is a list of all its dependencies, recursively, including absolutely everything necessary to use that derivation.

$ nix-store -qR `which man`
[...]
```console
$ nix-store -qR `which man`
[...]
```

Copying all those derivations to the Nix store of another machine makes you able to run `man` out of the box on that other machine. That's the base of deployment using Nix, and you can already foresee the potential when deploying software in the cloud (hint: `nix-copy-closures` and `nix-store --export`).

A nicer view of the closure:

$ nix-store -q --tree `which man`
[...]
```console
$ nix-store -q --tree `which man`
[...]
```

With the above command, you can find out exactly why a _runtime_ dependency, be it direct or indirect, exists for a given derivation.

Expand All @@ -145,10 +169,12 @@ There isn't anything like `apt` which solves a SAT problem in order to satisfy d

## Recovering the hard way

$ nix-env -e '*'
uninstalling 'hello-2.10'
uninstalling 'nix-2.1.3'
[...]
```console
$ nix-env -e '*'
uninstalling 'hello-2.10'
uninstalling 'nix-2.1.3'
[...]
```

Oops, that uninstalled all derivations from the environment, including Nix. That means we can't even run `nix-env`, what now?

Expand All @@ -158,18 +184,24 @@ First, pick one `nix-2.1.3` derivation: `ls /nix/store/*nix-2.1.3`, say `/nix/st

The first option is to rollback:

$ /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env --rollback
```console
$ /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env --rollback
```

The second option is to install Nix, thus creating a new generation:

$ /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env -i /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env
```console
$ /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env -i /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/bin/nix-env
```

## Channels

So where are we getting packages from? We said something about this already in the [second article](02-install-on-your-running.md). There's a list of channels from which we get packages, although usually we use a single channel. The tool to manage channels is [nix-channel](https://nixos.org/manual/nix/stable/command-ref/nix-channel.html).

$ nix-channel --list
nixpkgs http://nixos.org/channels/nixpkgs-unstable
```console
$ nix-channel --list
nixpkgs http://nixos.org/channels/nixpkgs-unstable
```

If you're using NixOS, you may not see any output from the above command (if you're using the default), or you may see a channel whose name begins with "nixos-" instead of "nixpkgs".

Expand Down
Loading

0 comments on commit 13c9916

Please sign in to comment.