When and how should default.nix, shell.nix and release.nix be used?

One of the first types of Nix expression one encounters when learning how to use the Nix package manager is default.nix; on the wonderful NixOS IRC channel I learned of the existence of shell.nix and release.nix as well.

I got the impression that - roughly -default.nix is to be used with nix-build for simply building the package, shell.nix is used with nix-shell to create an interactive environment with the package and release.nix is used with nixops in deploying the package.

Since this is likely incomplete and partially incorrect, and since this does not seem to be clearly documented, I would like a clear and precise explanation of these sorts of "standard files"; in particular, for each of these file types (as well as any other standard files I am missing), I would like to know:

  1. What are the typical use cases for such a file? What should they not be used for?
  2. How is this file type structured typically? What are the minimal requirements for it?
  3. Could you show a paradigm example of such a file within its use context, i.e. with use instructions and including lines of code needed to use it in the shell or another Nix expression?

As an additional bonus question, I want to know which - if any - of these standard files should be used when installing a package into a NixOS module? How would that be done?

20460 次浏览

First of all, default.nix and shell.nix have special meanings in Nix tool, but release.nix is a convenience one.

Next, default.nix is used as a default file when running nix-build, and shell.nix is used as a default file when running nix-shell. Just like you said.

Next, default.nix isn't used only for nix-build. For example, <nixpkgs/lib/default.nix> is used as aggregator for functions, and doesn't contain derivations. So not every default.nix is supposed to be "built" (but if default.nix is an attribute set of derivations, it will be buildable, and nix-build will build all of them).

Next, nix-shell will use default.nix if no shell.nix is found.

Next, default.nix is used as default file when importing directory. So if you write x = import ./some/directory;, then ./some/directory/default.nix will be imported. That actually should explain why "nix-build ." uses default.nix.

And finally, there are two common formats for derivations in default.nix: derivation, and callPackage derivation. You can't nix-build the latter. Almost any package in nixpkgs is written in this style, see hello. But you can nix-build -E 'with import <nixpkgs> { }; callPackage ./path/to/default.nix { }' as a workaround. nix-shell also supports this -E argument.

As said by @danbst only default.nix and shell.nix have special meanings for the nix tooling, out of that there is no real standard and everybody is free to use what fits most their needs.

That said, it doesn't mean you cannot set your own set of rules, personally for a single derivation project I like to arrange nix files in the following manner:

  • default.nix: Use callpackage to import derivation.nix.
  • derivation.nix: nixpkgs style derivation file.
  • shell.nix: nix-shell file.
  • module.nix: NixOS module file, import default.nix.
  • test.nix: NixOS test file.
  • release.nix: Hydra jobset declaration.

We had a talk about this topic at the Tokyo NixOS meetup, an example of a such code organization can be found here.