Unstable channel - undefined variable 'unstable'

Using Flakes and Home Manager, I am trying to enable the option to install some unstable packages. I found a nice “how-to” here, that I tried following.

  1. I added the unstable channel in flake.nix
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

  2. I defined an overlay flake.nix:

        unstable-packages = final: _prev: {
            unstable = import inputs.nixpkgs-unstable {
                system = final.system;
                config.allowUnfree = true;
            };
        };
  1. I imported the overlay in home.nix:
    nixpkgs.overlays = [
        outputs.unstable-packages
    ];
  1. I tried using the unstable channel:
    unstable.hyprlock

However, trying to rebuild I am met with:
error: undefined variable ‘unstable’

So, maybe the overlay is not imported correctly. But, I do not see why. Any help would be appreciated!

Full code:
flake.nix
home.nix

Home manager has its own special args rather interestingly named extraSpecialArgs. To pass the overlay to your home.nix, you’d might do something like this:

# flake.nix
{
  description = "Nixos config flake";

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

  outputs =
    inputs@{ self, nixpkgs, ... }:
    let
      system = "x86_64-linux";
      pkgs = import nixpkgs { inherit system; };
    in
    {
      unstable-packages = final: _prev: {
        unstable = import inputs.nixpkgs-unstable {
          system = final.system;
          config.allowUnfree = true;
        };
      };

      checks.${system}.test = pkgs.testers.runNixOSTest {
        name = "test";
        node.specialArgs = {
          inherit (self) inputs outputs;
        };
        nodes.machine1 =
          { config, pkgs, ... }:
          {
            services.getty.autologinUser = "alice";
            imports = [ inputs.home-manager.nixosModules.home-manager ];
            users.users.alice = {
              isNormalUser = true;
              password = "hunter2";
            };

            home-manager.extraSpecialArgs = { # specialArgs that home-manager uses; different from the node's specialArgs
              inherit (self) inputs outputs;
            };
            home-manager.users.alice =
              { config, ... }: # config is home-manager's config, not the OS one
              {
                imports = [ ./home.nix ];
                home.stateVersion = "23.11";
              };
          };
        testScript = "start_all()";
      };
    };
}

# home.nix
{
  inputs,
  outputs,
  lib,
  config,
  pkgs,
  ...
}:
{
  home.packages = [ pkgs.unstable.hyprlock ];
  nixpkgs.overlays = [ outputs.unstable-packages ];
}

In general, if the overlay were not applied, you would typically get an error like “pkgs has no foo attribute”, but with pkgs; in your code probably masks this resulting in the error you see. with scopes are a bit tricky.

1 Like

Thank you, @VTimofeenko. You pointed me in the right direction. I did not have to use home-manager.extraSpecialArgs though, by some reason specialArgs is sufficient. Maybe inputs and outputs are adutomatically passed on to home-manager? I found out that there was defined an overlay in configuration.nix, and this overwrote the overlay array. That is why the overlay was not applied.

To summarise:

  1. flake.nix - inputs:
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

  2. flake.nix - outputs (in the in { } block):

        unstable-packages = final: _prev: {
            unstable = import inputs.nixpkgs-unstable {
                system = final.system;
                config.allowUnfree = true;
            };
        };
  1. configuration.nix (imported by home.nix):
    nixpkgs.overlays = [
            outputs.unstable-packages
     ];
  1. home.nix:
    home.packages = with pkgs; [
        unstable.hyprlock
    ];

An overlay is complete overkill here. Just add your inputs to extraSpecialArgs and use nixpkgs-unstable directly:

home.packages = [
  inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.hyprlock
];

Also, avoid import-ing nixpkgs when you can, it’s totally unnecessary here (although it’s also not terribly harmful, just a good habit to get into). It’s basically only useful when you do want to use an unfree package, in which case there is nixpkgs-unfree for until flakes have a better solution.

1 Like

Thank you for the information, @TLATER. That way of solving this is nice and clean. I have already re-written my code, doing it the suggested way.

A few additional questions:
What does legacyPackages mean? And, how can I list all unstable legacy packages in the nixpkgs repo? Is it simply all pkgs packages?

Initially, I though that the last part of a github source url, after the dash, was pointing to a tag. I can find the 23.11 tag, but not the unstable tag, so I guess I am wrong about this assumption.

Flakes have this new idea that packages should appear in a flat structure. Nixpkgs predates flakes by many years, and some of its package sets are nested (e.g. pythonxxPackages.*).

The flake proposal needed an escape hatch to allow nixpkgs to fit the proposal. That’s legacyPackages - simply a set or packages that doesn’t need to be flat.

nixpkgs.legacyPackages just contains everything you would normally see in pkgs, but it hits the evaluation cache and other flake features.

You can use nix search for that.

But yeah, pretty much.

This is more obvious when you see the non-url form, but it is a rev, which can be a tag or a branch (and in fact a specific commit).

For unstable, it’s customary to use the nixos-unstable branch instead of e.g. nixos-23.11.

If they were tags, you wouldn’t get any updates :wink:

1 Like

legacyPackages is somewhat unfortunately named packages, see this comment in nixpkgs flake. Two of the hardest things in computing are cache invalidation and naming things.

Initially, I though that the last part of a github source url, after the dash, was pointing to a tag

Sort of. See “Flake references” in the manual

1 Like

Thanks a lot for the knowledge sharing. I appreciate getting answers to my basic questions, as this is helpful information for a NixOS beginner.
As well, since the best solution seems to be using nixpkgs-unstable directly, I will update the solution to this thread. Simply to guide new readers that might not read all the posts.

1 Like