How to have multiple pinned NixOS versions in one flake?

I’m working on getting all my home-manager and NixOS configurations set up in a single flake. I want my home-manager profiles to all use the unstable branch of nixpkgs. My NixOS configurations are using a variety of different releases of NixOS (I’m working on getting them upgrades as I go).

While trying to upgrade from 24.11 to 25.05, I found that I’ve been setting these versions incorectly:

flake.nix

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs-25_05.url = "github:nixos/nixpkgs/nixos-25.05";
  };

  outputs =
    {
      nixpkgs,
      home-manager,
      nixpkgs-25_05,
      ...
    }@inputs:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
    in
    {
      # home-manager stuff using `pkgs`

      nixosConfigurations.myhost = nixpkgs-25_05.lib.nixosSystem {
        inherit system;
        specialArgs = {
          pkgs = nixpkgs-25_05.legacyPackages.${system};
        };
        modules = [
          ./hosts/mc/configuration.nix
        ];
      };
    };

}

This worked while I was using 24.11, but now I get a warning about setting specialArgs.pkgs:

$ nix flake check
evaluation warning: You have set specialArgs.pkgs, which means that options like nixpkgs.config
                    and nixpkgs.overlays will be ignored. If you wish to reuse an already created
                    pkgs, which you know is configured correctly for this NixOS configuration,
                    please import the `nixosModules.readOnlyPkgs` module from the nixpkgs flake or
                    `(modulesPath + "/misc/nixpkgs/read-only.nix"), and set `{ nixpkgs.pkgs = <your pkgs>; }`.
                    This properly disables the ignored options to prevent future surprises.

I tried following the advice from the warning / Google, and got this:

      nixosConfigurations.myhost = nixpkgs-25_05.lib.nixosSystem {
        inherit system;
        modules = [
          ./hosts/mc/configuration.nix
          nixpkgs.nixosModules.readOnlyPkgs
          { nixpkgs.pkgs = nixpkgs-25_05.legacyPackages.${system}; }
        ];
      };

but now I get the following error:

$ nix flake check
      error: The option `nixpkgs.config' in `/nix/store/3p306srz83h9z9v0ma9xcxb8y8cdxkxj-source/nixos/modules/misc/nixpkgs.nix' is already declared in `/nix/store/xzl5dhddgjxp2p18h5qpkhvlkp8128j1-source/nixos/modules/misc/nixpkgs/read-only.nix'.

so I’ve clearly done something wrong.

I know that I can pass nixpkgs-25_05 as an argument to my modules, but my concern is that then I have to remember to use the right variable in all my configs. I also wouldn’t be able to control which version of nixpkgs would be used by other modules that my configs depend on. I want everything on myhost to come only from the pinned NixOS release.

Why are you trying to set pkgs manually at all? It’s going to be generated from the nixpkgs that you get nixosSystem from anyway. Let it be generated normally.

It’s very rarely a good idea to set pkgs yourself. If you find yourself doing it, take a step back and think about why you think it’s necessary, and what you really gain by doing so.

That said, for completeness’ sake, I’ll also point out what you did wrong: you used nixpkgs.nixosModules.readOnlyPkgs rather than nixpkgs-25_05.nixosModules.readOnlyPkgs. Make sure to combine things from the same nixpkgs unless you have good reason not to.

2 Likes

Yeah there’s basically no reason to set this. lib.nixosSystem (via the nixpkgs NixOS module from the associated nixpkgs ref) will already give you the correct pkgs as a module arg:

And if you use readOnlyPkgs you’ll break every definition for options under nixpkgs.* in your NixOS config.

Why are you trying to set pkgs manually at all? It’s going to be generated from the nixpkgs that you get nixosSystem from anyway. Let it be generated normally.

You know, now that I’m looking back I’m not sure where I got the idea that I needed to set pkgs myself. I think I must have gotten confused and replaced an inherit system with inherit pkgs at some point and gone off track from there.

Thank you for your help!