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

157 lines
4.4 KiB
ReStructuredText
Raw Normal View History

2020-07-09 06:13:04 -04:00
.. _declarative-reproducible-envs:
2020-05-22 04:17:14 -04:00
Declarative and reproducible developer environments
===================================================
2020-07-09 06:09:24 -04:00
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 are declarative shell environments useful?
-----------------------------------------------
This is the quickest approach to getting started with Nix:
2020-07-09 06:09:24 -04:00
- use single command to invoke it via ``nix-shell``
- it works across different operating systems (Linux / MacOS)
- you share the exact same environment with all developers
Developer environments allow you to:
2020-05-18 04:52:41 -04:00
- 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
2020-07-01 09:54:41 -04:00
Getting started
---------------
2020-07-09 06:09:24 -04:00
At the top-level of your project create ``shell.nix`` with the following contents:
2020-05-18 04:52:41 -04:00
2020-05-18 05:41:12 -04:00
.. code:: nix
2020-05-18 04:52:41 -04:00
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/3590f02e7d5760e52072c1a729ee2250b5560746.tar.gz") {} }:
2020-05-18 04:52:41 -04:00
pkgs.mkShell {
buildInputs = [
pkgs.which
pkgs.htop
pkgs.zlib
2020-05-18 04:52:41 -04:00
];
}
2020-07-01 09:54:41 -04:00
.. 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:
2020-05-18 04:52:41 -04:00
.. code:: shell-session
2020-05-18 04:52:41 -04:00
$ 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'...
2020-05-18 04:52:41 -04:00
[nix-shell:~]$
2020-07-09 06:09:24 -04:00
The command will start downloading the missing packages from the https://cache.nixos.org binary cache.
2020-06-25 05:49:16 -04:00
Once it's done, you are dropped into a new
2020-05-18 04:52:41 -04:00
shell. This shell provides the packages specified in ``shell.nix``.
2020-07-09 06:09:24 -04:00
Run ``htop`` to confirm that it is present. Quit the program by hitting
``q``.
2020-05-18 04:52:41 -04:00
2020-07-09 06:09:24 -04:00
Now, try ``which htop`` to check where the ``htop`` command is on disk.
2020-05-18 04:52:41 -04:00
You should see something similar to this:
.. code:: shell-session
2020-05-18 04:52:41 -04:00
[nix-shell:~]$ which htop
2020-05-18 04:52:41 -04:00
/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
2020-07-09 06:09:24 -04:00
- 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
------------------------------------------------------------------------
2020-07-09 06:09:24 -04:00
Besides activating the environment for each project, every time you change
``shell.nix`` you need to re-enter the shell.
2020-07-09 06:09:24 -04:00
You can use ``direnv`` to automate this process for you, with the downside that each developer needs
to install it globally.
2020-07-09 06:09:24 -04:00
Setting up ``direnv``
*********************
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
2020-07-09 06:09:24 -04:00
The next time your launch your terminal and enter the top-level of your project direnv will check for changes.
.. code:: shell-session
$ cd myproject
direnv: loading myproject/.envrc
direnv: using nix
hello
2020-05-18 04:52:41 -04:00
2021-06-15 10:58:33 -04:00
Next steps
----------
2020-05-18 04:52:41 -04:00
2020-07-07 04:49:02 -04:00
- :ref:`pinning-nixpkgs` to see different ways to import nixpkgs
2020-07-09 06:09:24 -04:00
- To quickly set up a Nix project read through
`Getting started Nix template <https://github.com/nix-dot-dev/getting-started-nix-template>`_.