1
0
Fork 0
mirror of https://github.com/NixOS/nix.dev.git synced 2024-10-18 14:32:43 -04:00
nix.dev/source/tutorials/declarative-and-reproducible-developer-environments.rst
Domen Kožar 0a2de10756
review
2020-07-01 15:54:41 +02:00

155 lines
4.1 KiB
ReStructuredText

.. _declarative-reproducible-envs:
Declarative and reproducible developer environments
===================================================
In :ref:`ad-hoc-envs` tutorial we took a dive into 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 are declarative shell environments useful?
-----------------------------------------------
This is the quickest approach to getting started with Nix:
- single command to invoke it via ``nix-shell``
- 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
---------------
In top-level of your project create ``shell.nix`` with the following contents:
.. code:: nix
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/3590f02e7d5760e52072c1a729ee2250b5560746.tar.gz") {} }:
pkgs.mkShell {
buildInputs = [
pkgs.which
pkgs.htop
pkgs.zlib
];
}
.. note:: To understand the first line, read through :ref:`pinning nixpkgs tutorial <ref-pinning-nixpkgs>`.
We import ``nixpkgs`` and make a shell with ``which`` and ``htop`` available in ``$PATH``.
``zlib`` provides libraries and headers in case we're compiling something against it.
To enter the environment:
.. code:: shell-session
$ 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:~]$
The command will start downloading the missing packages from https://cache.nixos.org binary cache.
Once it's done, you are dropped into a new
shell. This shell provides the packages specified in ``shell.nix``.
Run ``htop`` to confirm 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:
.. code:: shell-session
[nix-shell:~]$ which htop
/nix/store/y3w2i8kfdbfj9rx287ad52rahjpgv423-htop-2.2.0/bin/htop
Customizing your developer environment
--------------------------------------
Given the following ``shell.nix``:
.. code:: nix
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/3590f02e7d5760e52072c1a729ee2250b5560746.tar.gz") {} }:
pkgs.mkShell {
buildInputs = [
pkgs.which
pkgs.htop
pkgs.zlib
];
shellHook = ''
echo hello
'';
MY_ENVIRONMENT_VARIABLE = "world";
}
Running ``nix-shell`` we observe:
.. code:: shell-session
$ nix-shell
hello
[nix-shell:~]$ echo $MY_ENVIRONMENT_VARIABLE
world
- ``shellHook`` allows you to execute bash while entering the shell environment
- attributes passed to ``mkShell`` function are available once shell environment is active
``direnv``: Automatically activating the environment on directory change
------------------------------------------------------------------------
Besides activating environment for each project, everytime you change
``shell.nix`` you need to re-enter the shell.
``direnv`` automates it for you with the downside that each developer needs
to install it globally.
Setup:
1. `Install direnv with your OS package manager <https://direnv.net/docs/installation.html#from-system-packages>`_
2. `Hook it into your shell <https://direnv.net/docs/hook.html>`_
At the top-level of your project run::
echo "use nix" > .envrc && direnv allow
The next time your launch terminal and enter top-level of your project:
.. code:: shell-session
$ cd myproject
direnv: loading myproject/.envrc
direnv: using nix
hello
Going forward
-------------
- :ref:`pinning-nixpkgs` to see different ways to import nixpkgs