mirror of
https://github.com/nix-community/nix-direnv.git
synced 2025-11-08 19:46:11 +01:00
291 lines
8 KiB
Markdown
291 lines
8 KiB
Markdown
# nix-direnv
|
|
|
|

|
|
|
|
A faster, persistent implementation of `direnv`'s `use_nix`, to replace the built-in one.
|
|
|
|
Prominent features:
|
|
|
|
- significantly faster after the first run by caching the `nix-shell` environment
|
|
- prevents garbage collection of build dependencies by symlinking the resulting
|
|
shell derivation in the user's `gcroots` (Life is too short to lose
|
|
your project's build cache if you are on a flight with no internet connection)
|
|
|
|
## Installation
|
|
|
|
There are different ways to install nix-direnv, pick your favourite:
|
|
|
|
- via home-manager (recommended)
|
|
- via configuration.nix in NixOS
|
|
- with nix-env
|
|
- from source
|
|
- with direnv source_url
|
|
|
|
### Via home-manager
|
|
|
|
In `$HOME/.config/nixpkgs/home.nix` add
|
|
|
|
```Nix
|
|
{ pkgs, ... }:
|
|
|
|
{
|
|
# ...other config, other config...
|
|
|
|
programs.direnv.enable = true;
|
|
programs.direnv.nix-direnv.enable = true;
|
|
# optional for nix flakes support
|
|
programs.direnv.nix-direnv.enableFlakes = true;
|
|
|
|
programs.bash.enable = true;
|
|
# OR
|
|
programs.zsh.enable = true;
|
|
# Or any other shell you're using.
|
|
}
|
|
```
|
|
|
|
Optional: To protect your nix-shell against garbage collection you also need to add these options to your Nix configuration.
|
|
|
|
If you are on NixOS also add the following lines to your `/etc/nixos/configuration.nix`:
|
|
|
|
```Nix
|
|
{ pkgs, ... }: {
|
|
nix.extraOptions = ''
|
|
keep-outputs = true
|
|
keep-derivations = true
|
|
'';
|
|
}
|
|
```
|
|
|
|
On other systems with Nix add the following configuration to your `/etc/nix/nix.conf`:
|
|
|
|
```
|
|
keep-derivations = true
|
|
keep-outputs = true
|
|
```
|
|
|
|
### Via configuration.nix in NixOS
|
|
|
|
In `/etc/nixos/configuration.nix`:
|
|
|
|
```Nix
|
|
{ pkgs, ... }: {
|
|
environment.systemPackages = with pkgs; [ direnv nix-direnv ];
|
|
# nix options for derivations to persist garbage collection
|
|
nix.extraOptions = ''
|
|
keep-outputs = true
|
|
keep-derivations = true
|
|
'';
|
|
environment.pathsToLink = [
|
|
"/share/nix-direnv"
|
|
];
|
|
# if you also want support for flakes (this makes nix-direnv use the
|
|
# unstable version of nix):
|
|
nixpkgs.overlays = [
|
|
(self: super: { nix-direnv = super.nix-direnv.override { enableFlakes = true; }; } )
|
|
];
|
|
}
|
|
```
|
|
|
|
Then source the `direnvrc` from this repository in your own `$HOME/.direnvrc`
|
|
|
|
```bash
|
|
# put this in ~/.direnvrc
|
|
source /run/current-system/sw/share/nix-direnv/direnvrc
|
|
```
|
|
|
|
### With nix-env
|
|
|
|
As **non-root** user do the following:
|
|
|
|
```console
|
|
nix-env -f '<nixpkgs>' -iA nix-direnv
|
|
```
|
|
|
|
Then add nix-direnv to `$HOME/.direnvrc`:
|
|
|
|
```bash
|
|
source $HOME/.nix-profile/share/nix-direnv/direnvrc
|
|
```
|
|
|
|
You also need to set `keep-outputs` and `keep-derivations` to nix.conf as described in the installation
|
|
via home-manager section.
|
|
|
|
### From source
|
|
|
|
Clone the repository to some directory
|
|
|
|
```console
|
|
$ git clone https://github.com/nix-community/nix-direnv $HOME/nix-direnv
|
|
```
|
|
|
|
Then source the direnvrc from this repository in your own `.direnvrc`
|
|
|
|
```bash
|
|
# put this in ~/.direnvrc
|
|
source $HOME/nix-direnv/direnvrc
|
|
```
|
|
|
|
You also need to set `keep-outputs` and `keep-derivations` to nix.conf as described in the installation
|
|
via home-manager section.
|
|
|
|
### Direnv source_url
|
|
|
|
Put the following lines in your `.envrc`:
|
|
|
|
```bash
|
|
if ! has nix_direnv_version || ! nix_direnv_version 1.5.0; then
|
|
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/1.5.0/direnvrc" "sha256-sha256-carKk9aUFHMuHt+IWh74hFj58nY4K3uywpZbwXX0BTI="
|
|
fi
|
|
```
|
|
|
|
## Usage example
|
|
|
|
Either add `shell.nix` or a `default.nix` to the same directory:
|
|
|
|
``` nix
|
|
# save this as shell.nix
|
|
{ pkgs ? import <nixpkgs> {}}:
|
|
|
|
pkgs.mkShell {
|
|
nativeBuildInputs = [ pkgs.hello ];
|
|
}
|
|
```
|
|
|
|
Then add the line `use nix` to your envrc:
|
|
```console
|
|
$ echo "use nix" >> .envrc
|
|
$ direnv allow
|
|
```
|
|
|
|
If you haven't used direnv before, make sure to [hook it into your shell](https://direnv.net/docs/hook.html) first.
|
|
|
|
### Using a non-standard file name
|
|
You may use a different file name than `shell.nix` or `default.nix` by passing the file name in `.envrc`, e.g.:
|
|
```console
|
|
$ echo "use nix foo.nix" >> .envrc
|
|
```
|
|
|
|
## Flakes support
|
|
|
|
nix-direnv also comes with a flake alternative. The code is tested and works however
|
|
since future nix versions might change their api regarding this feature we cannot
|
|
guarantee stability after an nix upgrade.
|
|
Likewise `use_nix` the `use_flake` implementation will prevent garbage
|
|
collection of downloaded packages and also for flake inputs.
|
|
|
|
You can run `nix flake new -t github:nix-community/nix-direnv` to get [this](https://github.com/nix-community/nix-direnv/tree/master/template) project template.
|
|
or just add:
|
|
|
|
```
|
|
$ echo "use flake" >> .envrc
|
|
$ direnv allow
|
|
```
|
|
|
|
in case the project already comes with a `flake.nix`.
|
|
Optionally if you do not want flake.nix to be part of the current directory repo,
|
|
you can specify an arbitrary flake expression as parameter such as:
|
|
|
|
```console
|
|
use flake ~/myflakes#project
|
|
```
|
|
|
|
## Storing .direnv outside the project directory
|
|
|
|
A `.direnv` directory will be created in each `use_nix` project, which might
|
|
interact badly with backups (e.g. Dropbox) or IDEs.
|
|
|
|
Therefore it's possible to override a function called `direnv_layout_dir` in
|
|
`$HOME/.config/direnv/direnvrc` or in each project's `.envrc`.
|
|
|
|
The following example will create a unique directory name per project
|
|
in `$HOME/.cache/direnv/layouts/`:
|
|
|
|
```bash
|
|
# $HOME/.config/direnv/direnvrc
|
|
: ${XDG_CACHE_HOME:=$HOME/.cache}
|
|
declare -A direnv_layout_dirs
|
|
direnv_layout_dir() {
|
|
echo "${direnv_layout_dirs[$PWD]:=$(
|
|
echo -n "$XDG_CACHE_HOME"/direnv/layouts/
|
|
echo -n "$PWD" | shasum | cut -d ' ' -f 1
|
|
)}"
|
|
}
|
|
```
|
|
During direnv setup `direnv_layout_dir` can be called multiple times and with different values of `$PWD`
|
|
(when other `.envrc` files are included). Therefore cache its results in dictionary `direnv_layout_dirs`.
|
|
|
|
## Manually re-triggering evaluation
|
|
|
|
In some case nix-direnv does not detect if imported file has changed and still
|
|
provides the old cached values. An evaluation can be triggered by updating your
|
|
`default.nix`, `shell.nix` or `flake.nix`, depending on what is used:
|
|
|
|
```console
|
|
# choose one
|
|
$ touch default.nix
|
|
$ touch shell.nix
|
|
$ touch flake.nix
|
|
```
|
|
|
|
## Shell integration
|
|
|
|
To quickly add a default.nix/flake.nix to a project you can put the following snippets in your bashrc/zshrc
|
|
|
|
```bash
|
|
nixify() {
|
|
if [ ! -e ./.envrc ]; then
|
|
echo "use nix" > .envrc
|
|
direnv allow
|
|
fi
|
|
if [[ ! -e shell.nix ]] && [[ ! -e default.nix ]]; then
|
|
cat > default.nix <<'EOF'
|
|
with import <nixpkgs> {};
|
|
mkShell {
|
|
nativeBuildInputs = [
|
|
bashInteractive
|
|
];
|
|
}
|
|
EOF
|
|
${EDITOR:-vim} default.nix
|
|
fi
|
|
}
|
|
|
|
flakifiy() {
|
|
if [ ! -e flake.nix ]; then
|
|
nix flake new -t github:nix-community/nix-direnv .
|
|
elif [ ! -e .envrc ]; then
|
|
echo "use flake" > .envrc
|
|
direnv allow
|
|
fi
|
|
${EDITOR:-vim} flake.nix
|
|
}
|
|
|
|
```
|
|
|
|
## Known Bugs
|
|
|
|
At the moment `nix-direnv` depends on GNU Grep and a modern Bash version.
|
|
This might lead to [problems](https://github.com/nix-community/nix-direnv/issues/3) on macOS.
|
|
As a work-around we suggest that macOS users install `direnv`/`grep` via Nix or Homebrew.
|
|
|
|
## Why not use `lorri` instead?
|
|
|
|
- nix-direnv has flakes support.
|
|
- High CPU load/resource usage in some cases: When nixpkgs in `NIX_PATH` is
|
|
pointed to a directory, i.e. a git checkout, Lorri will try to evaluate
|
|
nixpkgs everytime something changes causing high cpu load. Nix-direnv
|
|
compromises between performance and correctness, and only re-evaluates direnv
|
|
if either the project-specific `default.nix` / `shell.nix` changes, or if
|
|
there is a new commit added to `nixpkgs`. A re-evaluation can be also
|
|
triggered by using `touch .envrc` in the same project.
|
|
A different problem is that it might trigger mass-rebuilds when the same nixpkgs
|
|
checkout is pointed to something like staging.
|
|
- No additional daemon or services required: The codesize is small enough that it can be vendored
|
|
into a project itself.
|
|
|
|
## Other projects in the field
|
|
|
|
- [lorri](https://github.com/nix-community/lorri)
|
|
- [sorri](https://github.com/nmattia/sorri)
|
|
- [nixify](https://github.com/kalbasit/nur-packages/blob/master/pkgs/nixify/envrc)
|
|
- [direnv-nix-lorelei](https://github.com/shajra/direnv-nix-lorelei)
|