The nixpkgs flake import

When recently flakifying a simple project from default.nix to flake, I used this idiom:

  description = "…;

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-21.11";

  outputs = { self, nixpkgs, nix-filter }:
      pkgs = pkgs = nixpkgs.legacyPackages.x86_64-linux;

which makes sense to me, given that nixpkg’s flake.nix says

      legacyPackages = forAllSystems (system: import ./. { inherit system; });

in its output, and given that the nix-flake docs says:

outputs: A function that, given an attribute set containing the outputs of each of the input flakes keyed by their identifier, yields the Nix values provided by this flake. Thus, in the example above, inputs.nixpkgs contains the result of the call to the outputs function of the nixpkgs flake file.

But then I find I have to change the nixpkgs instantiation a bit, e.g. add an overlay, and I write

  description = "…;

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-21.11";
  inputs.nix-filter.url = "github:numtide/nix-filter";

  outputs = { self, nixpkgs, nix-filter }:
      pkgs = import nixpkgs {
        system = "x86_64-linux";
        overlays = [ nix-filter.overlays.default ];

How does that work? Isn’t nixpkgs here a set, and import expects a path or string?

Independently of the “how”, is this the idiomatic style? Using the nixpkgs outputs directly when possible, and using import nixpkgs { … } else?

nixpkgs has outPath, which is a path that can be used by import


And implicit does that implicitly? (I saw it in the code, but not the docs, maybe I should add a PR.)

Also, shouldn’t that attribute be some where in, or how does it end up there?

I’m not sure what you’re referring to. I’m not familiar with Nix’s source code

Nix does this automatically when it fetches the flake inputs

The outPath attribute and others are added by Nix itself

1 Like

I recently found that you can apply overlays like this

nixpkgs.legacyPackages.${system}.extend overlay

and also

nixpkgs.legacyPackages.${system}.appendOverlays [ overlay1 overlay2 ]

but I’m not sure if that’s any better than importing wrt to avoiding unnecessary evaluations of nixpkgs, since it relies on

nixpkgsFun = newArgs: import ./. (args // newArgs)

Also, I wonder if it’s possible to similarly set config.allowUnfree = true, without importing.

Ah, thanks, that puts the pieces together. I’ll PR a few minor documentation amendments:

1 Like