Using an unstable package inside of a flake

Hi, I am a beginner user of NixOS. I am configuring my system using a flake entry point. I think this is a common case but after reading multiple posts I can’t figure out what I am doing wrong in this flake. My main goal is to use the unstable branch for a specific package. Please consider this case:

flake.nix
  {    
    inputs = {    
      nixpkgs = {url = "github:nixos/nixpkgs/23.05";};    
      unstable.url = "github:nixos/nixpkgs/nixos-unstable";    
    };    
      
    outputs = {    
      self,      
      nixpkgs,    
      unstable,    
    }: {    
      nixosConfigurations = {    
        nixos = nixpkgs.lib.nixosSystem {    
          modules = [    
            ./nixos/configuration.nix    
          ];       
          specialArgs = { inherit unstable; };    
        };    
      };    
    };    
  } 

This is the summary of configuration.nix:

configuration.nix
  { pkgs, unstable, ... }: {    
    environment.systemPackages = [
       git
       unstable.jq
    ]
  } 

This is just an example, the actual configuration is bigger. With this, I get the following error:

error: attribute 'jq' missing

After reading some posts, I’ve tried with nix repl. I can do :lf . and print what is inputs.unstable, and indeed it doesn’t have the jq property, although I am not sure if this gets transformed after reaching the function inside configuration.nix (since nixpkgs doesn’t have it either).

This is probably a beginner’s misunderstanding of how these inputs get processed. How can I use an unstable package (in this case jq) in a flake with multiple inputs, in which the configuration is referenced inside nixpkgs.lib.nixosSystem? Is there a way I could debug this with nix repl or another?

1 Like

I’ve found a solution, although not sure if it is the correct approach. Marking this as resolved but I can delete the topic if preferred, and of course would appreciate any extra information.

This way of selecting the package worked:

environment.systemPackages = [
  unstable.legacyPackages."${pkgs.system}".jq
]
1 Like

It is the correct approach.

This is how nixpkgs exposes its packages.

The “legacy” in legacyPackages does not mean that the content would be legacy and/or deprecated, it is just that nixpkgs does not fullfil the requirements of the packages output and it is not a trivial task to make it adhere to those.

Therefore legacyPackages is there to support the “legacy” we inherit from the grown complexity of nixpkgs that predates the sunset of flakes.

1 Like

I have also use something along the lines of

let
unstablePkgs = import inputs.nixpkgsUnstable {
  system = mySystem;
} in ...

Then use unstablePkgs.desiredPackage in place of legacyPackages. Is this the wrong approach, or just a different one?

It is another commonly used approach.

This is especially useful if you want to use unfree software from the other input or requires other specific nixpkgs-settings passed.