RITZA language edit.
4.1 KiB
(declarative-reproducible-envs)=
Declarative and reproducible developer environments
In the {ref}ad-hoc-envs
tutorial we looked at providing shell environments for when we need a quick 'n dirty way of getting hold of some tools.
In this tutorial, we'll take a look how to create {term}reproducible
shell environments given a declarative configuration file called a Nix expression.
When is a declarative shell environment useful?
A declarative shell environment is the quickest approach to getting started with Nix:
- Use a single command to invoke it via
nix-shell
. - It works across different operating systems (Linux / MacOS).
- Share the exact same environment with all developers.
Developer environments allow you to:
- Provide CLI tools, such as
psql
,jq
,tmux
, etc. - Provide developer libraries, such as
zlib
,openssl
, etc. - Set shell environment variables.
- Execute bash during environment activation.
Getting started
At the top-level of your project create shell.nix
with the following contents:
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/06278c77b5d162e62df170fec307e83f1812d94b.tar.gz") {} }:
pkgs.mkShell {
buildInputs = [
pkgs.which
pkgs.htop
pkgs.zlib
];
}
:::{note}
To understand the first line, read our tutorial on {ref}pinning Nixpkgs
.
:::
We import nixpkgs
and make a shell with which
and htop
available in $PATH
. We use zlib
to provide libraries and headers in case we're compiling something against it.
To enter the environment:
$ nix-shell
these paths will be fetched (0.07 MiB download, 0.20 MiB unpacked):
/nix/store/072a6x7rwv5f8wr6f5s1rq8nnm767cfp-htop-2.2.0
copying path '/nix/store/072a6x7rwv5f8wr6f5s1rq8nnm767cfp-htop-2.2.0' from 'https://cache.nixos.org'...
[nix-shell:~]$
This command will start downloading the missing packages from the https://cache.nixos.org binary cache.
Once the download is done, you are dropped into a new shell. This shell provides the packages specified in shell.nix
.
Run htop
to confirm that it is present. Quit the program by hitting q
.
Now try which htop
to check where the htop
command is on disk. You should see something similar to this:
[nix-shell:~]$ which htop
/nix/store/y3w2i8kfdbfj9rx287ad52rahjpgv423-htop-2.2.0/bin/htop
Customizing your developer environment
Given the following shell.nix
:
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/06278c77b5d162e62df170fec307e83f1812d94b.tar.gz") {} }:
pkgs.mkShell {
buildInputs = [
pkgs.which
pkgs.htop
pkgs.zlib
];
shellHook = ''
echo hello
'';
MY_ENVIRONMENT_VARIABLE = "world";
}
Running nix-shell
we observe:
$ nix-shell
hello
[nix-shell:~]$ echo $MY_ENVIRONMENT_VARIABLE
world
- The
shellHook
section allows you to execute bash while entering the shell environment. - Any attributes passed to
mkShell
function are available once the shell environment is active.
direnv
: Automatically activating the environment on directory change
Besides activating the environment for each project, every time you change shell.nix
you need to re-enter the shell.
You can use direnv
to automate this process for you, with the downside that each developer needs to install it globally.
Setting up direnv
At the top-level of your project run:
$ echo "use nix" > .envrc && direnv allow
The next time you launch your terminal and enter the top-level of your project, direnv
will check for changes.
$ cd myproject
direnv: loading myproject/.envrc
direnv: using nix
hello
Next steps
- Take a look at our {ref}
pinning Nixpkgs
tutorial to see different ways to import Nixpkgs. - To quickly set up a Nix project, read Getting started Nix template.