Is it possible to define two nixosSystems in a flake which are pinned to different NixOS releases?
Yup, just have two different nixpkgs inputs to your flake, one for each system, and pin those to different versions
This sounds very easy, but how can I pin this version. I haven’t found any example yet.
You can do explicit pinning by passing the revision in the input URL. If you just want to have e.g. 23.11 for one system and unstable for the other, add both to your inputs and pass the desired one(s) to each system. They will be pinned in you flake.lock and you can update them independently.
An example for what that could look like, from my nixos config: https://github.com/futile/nixos-config/blob/e1c6a21a48bd0ef0ddebd67370b376eb54ff92e2/flake.nix#L4-L47
See how I have some different nixpkgs-
inputs, and also see the fish-tide
input, which pins to a specific version of the repo.
Also see the official docs for the flake input schema: nix flake - Nix Reference Manual
Looking at your example I would expect your work-host to run nixos-2211 and your home-host to run nixos-2311. This would mean both run two completely different Gnome Versions and Kernel versions without explicitly pin every single package to use this nixos-version.
Is this possible?
Well, currently both run on nixos-unstable
, but yeah, I could have them running on different nixos versions, i.e., one could run nixos-23.05
and the other nixos-unstable
. It’s very possible, as you can see You just use two different nixpkgs-versions as inputs, and then use one for one system, and the other one for the other. You can even upgrade the entries in flake.lock
individually, i…e, nix flake lock --update-input one-of-the-two-inputs-only
will only update one of the inputs.
I still don’t see it. I can only specify one inputs
object and inside this object only one nixpkgs
. How can I tell lib.nixosSystem
to use nixpkgs-unstable
for nixos-work
and use nixpkgs
for nixos-home
?
inputs = {
nixpkgs = { url = "github:nixos/nixpkgs/nixos-23.05"; };
nixpkgs-unstable = { url = "github:nixos/nixpkgs/nixos-unstable"; };
};
outputs = { self, nixpkgs, nixpkgs-unstable... }@inputs:
let
system = "x86_64-linux";
in
{
#### This uses: nixpkgs. No problem
nixosConfigurations.nixos-home = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./hosts/nixos-home
];
};
#### This should use: nixpkgs-unstable... How?
nixosConfigurations.nixos-work = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./hosts/nixos-work
];
};
};
}
# ...
nixosConfigurations.nixos-work = nixpkgs-unstable.lib.nixosSystem {
#...
};
# ...
This does not work. This only calls the lib.nixosSystem
function from nixpkgs-unstable
in stead of nixpkgs
. The work system will still run the version of nixpkgs
Ah, yes. You also need to pass the unstable packages to the module system.
You can e.g.
upkgs = import nixpkgs-unstable { inherit system; };
# ...
modules = [
{ nixpkgs.pkgs = upkgs; }
# ..
];
or maybe a bit less hacky via specialArgs = {pkgs=upkgs;}
Wait, what? How does nixpkgs-unstable.lib.nixosSystem
get a handle on the other nixpkgs
input? There are no channels involved, so it should not be able to get arbitrary nixpkgses out of thin air?
Edit: Yeah, it imports the eval-config from the input in question, and uses self.lib
to eval. There’s no magic reference to a <nixpkgs>
or inputs.nixpkgs
or anything - what am I missing?
When doing it this way I get the error:
Failed assertions:
- Your system configures nixpkgs with an externally created instance.
`nixpkgs.config` options should be passed when creating the instance instead.
But when using nixpkgs.config.pkgs
it works!
upkgs = import nixpkgs-unstable { inherit system; };
# ...
modules = [
{ nixpkgs.config.pkgs = upkgs; }
# ..
];
This problem was bothering me for months already. I feel I have entered a new NixOS level. Thanks!
Maybe of help for others, here is a complete example:
{
inputs = {
nixpkgs = { url = "github:nixos/nixpkgs/nixos-23.11"; };
nixpkgs-unstable = { url = "github:nixos/nixpkgs/nixos-unstable"; };
};
outputs = { self, nixpkgs, nixpkgs-unstable... }@inputs:
let
system = "x86_64-linux";
in
{
nixosConfigurations.nixos-home = nixpkgs.lib.nixosSystem {
modules = [
./hosts/nixos-home
];
};
nixosConfigurations.nixos-work = nixpkgs-unstable.lib.nixosSystem {
modules = [
{
nixpkgs.config.pkgs = import nixpkgs-unstable { inherit system; };
}
./hosts/nixos-work
];
};
};
}
}
That was also my first thought, but then there is also automatic passing of arguments to modules and nixpkgs somehow being treated as a special name.
Yes, but all of that happens within the module system. At the flake.nix
level there should not be automated anything, and if you remame the nixpkgs
input to something else the whole system doesn’t break.