Is nix-shell impossible to pin package version and so flake is recommended?

Hi, I’m new to Nix and appreciate your kind advice.

If I understand correctly shell.nix is impossible (or difficult) to pin package version. Let’s say I defined nodejs_21 in buildInputs. If I run nix-shell at the end of 2023 I get v21.5.0 but at the end of January 2024 I get v21.6.0. It looks like lacking reproducibility and might be problematic in some situations.

On the other hands flake allows me to get same version every time thanks to lockfile. Is this one of the reason to use flake despite it is still experimental feature?

All you need to pin a version of Nixpkgs when using nix-shell is the -I command line argument.

nix-shell -p nodejs_21 -I nixpkgs=

You can also set this via the NIX_PATH environment variable, which might be a better fit for your development workflow if you use a tool like direnv.


I’m curious how you arrived at that conclusion. Could you provide a source that suggested this? Maybe we can clarify the documentation.

What did you do in the meantime? Although the mechanism for specifying impure sources for nix-shell (and other nix-* commands) is less visible, it doesn’t update references on its own.

Note that you can also have a shell.nix that imports a pinned version of Nixpkgs directly if you do not want to use a command-line parameter.

However, in any case you are not pinning nodejs version, you are pinning entire Nixpkgs (e.g. glibc included), so you opt out of all security updates not just the nodejs ones.