My setup is usually like this:
shell.nix
:
{ nixpkgs ? import (fetchGit {
url = https://github.com/NixOS/nixpkgs-channels;
ref = "nixpkgs-unstable";
}) {} }:
with nixpkgs;
mkShell {
buildInputs = [ ... ];
SOME_ENV_VAR = "foo";
shellHook = ''
# usually link in a nix-built vendor directory or other housekeeping
'';
}
for the already mentioned direnv, my super sophisticated .envrc
:
use nix
# optionally also some env vars, if they're supposed to be secret, otherwise they go into `shell.nix`.
My editor of choice is spacemacs, and I’m using emacs-direnv to automatically load my nix-shell
for each buffer so all dependencies are found.
For caching the nix-shell
I’m using the persistent cached shell variant of use nix
, but that’s pretty optional, just speeds things up a lot.
Depending on who I’m working with, I might try to keep all other nix things in a nix/
directory in the project, but I think having a shell.nix and default.nix at top-level is just good practice and easier to work with. So in the subdir go things like a common pinned nixpkgs version, dockertools, overlays, gemset.nix, etc…
To be honest I’m still experimenting with what I find the most comfortable project layout to work with, but after a few years this has been pretty much the standard I build on.