Problems after switching to flake system

I recently switched my system to use a flake, and I am having a few small problems with things that used to work before the conversion.

For instance, I used to be able to run a particular python script. Now when I try to run it, I get the following:

warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels/nixos' does not exist, ignoring
error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I)

       at «string»:1:25:

            1| {...}@args: with import <nixpkgs> args; (pkgs.runCommandCC or pkgs.runCommand) "shell" { buildInputs = [ (python3) (python39Packages.xlib) ]; } ""
             |                         ^
(use '--show-trace' to show detailed location information)

The first two lines of my python script look like this:

#!/usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 python39Packages.xlib

I’m sure it’s obvious, but I could use some help. Thanks.

You need to set up your NIX_PATH to match your flake inputs somehow. For example, in my config, I set nix.nixPath = [ "/etc/nix/path" ]; and then I can get a flake input into that nix path location with a line like environment.etc."nix/path/nixpkgs".source = nixpkgs;.

Once you have a nixpkgs in your NIX_PATH somehow, then commands (such as nix-shell) that depend on having a copy of a nixpkgs will work again.

Incidentally, the reason I don’t just set nix.nixPath directly to the store paths is that I want to be able to update online, and environment variables don’t really do that, so I indirect through a symlink I can update.

1 Like

Did you remove the channels? If so, this break a lot of things.

I did remove the channels. I thought that was what I was supposed to do. Should I re-enable them?

If so, which ones? System (i.e. sudo)? User? Home manager (https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager)?

You can certainly remove the channels, but if you do, you need to provide a copy of nixpkgs in NIX_PATH by some other mechanism to satisfy all the non-flake tools.

You can also just keep the channels, but that’s kind of ugly, because there are multiple versions of nixpkgs at play on your system in different ways.

I recommend removing channels and setting path to match your flake nixpkgs input.

Ex. Do flakes also set the system channel? - #2 by TLATER

OK. Let me see if I understand. You are recommending what @NobbZ did in that other post. I assume the relevant part is this:

config = lib.mkIf config.nix.flakes.enable {
  nix = {
    package = lib.mkDefault nix.packages.x86_64-linux.nix; # pkgs.nixUnstable;
    experimentalFeatures = "nix-command flakes";

          
    registry.nixpkgs.flake = unstable;
    registry.nixpkgs2105.flake = nixpkgs-2105;
    registry.nixpkgs2111.flake = nixpkgs-2111;

          
    nixPath = [
      "nixpkgs=${nixpkgsPath}"
      "nixpkgs2105=${nixpkgs2105Path}"
      "nixpkgs2111=${nixpkgs2111Path}"
      "/nix/var/nix/profiles/per-user/root/channels"
    ];
  };

Am I right? Does this go into my configuration.nix? I have a section that look like this:

  nix = {
    package = pkgs.nixFlakes;
    settings = {
      experimental-features = [ "nix-command" "flakes" ];
    };
  };

What changes should I make. This stuff is still so opaque to me… :frowning:

My flake.nix look like this:

{
  description = "NixOS configuration";

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

  outputs = { nixpkgs, home-manager, ... }:

  let
    system = "x86_64-linux";
    # pkgs = import nixpkgs {
    #   inherit system;
    #   # config = { allowUnfree = true; };
    # };
    lib = nixpkgs.lib;
    allowUnfreePredicate = pkg: true;

  in {
    homeManagerConfigurations = {
      user = home-manager.lib.homeManagerConfiguration {
        # inherit system pkgs;
        # inherit pkgs;
        pkgs = nixpkgs.legacyPackages.${system};
        modules = [
          ./users/user/home.nix
          {
            home = {
              username = "user";
              homeDirectory = "/home/user";
            };
          }
        ];
      };
    };

    nixosConfigurations = {
      framework = lib.nixosSystem {
        inherit system;
        modules = [
          ./system/configuration.nix
        ];
      };
    };
  };
}

First you need to pass your flake inputs into someplace you can get them in your nixos configuration. You can do that by changing ... }: to ... }@inputs: and adding a specialArgs = { inherit inputs; }; line to your lib.nixosSystem call, both in flake.nix.

Then add inputs to the list of arguments at the top of your configuration.nix.

Then you can add this to that nix section in your config:

nixPath = [ "/etc/nix/path" ];
registry.nixpkgs.flake = inputs.nixpkgs;

The registry line isn’t directly necessary for this part, but probably something you want anyway. It affects what happens when, for example, you type nix run nixpkgs#foo at the command line. You can also take out the package = pkgs.nixFlakes; line, incidentally, since flakes are now available in stable nix.

Then add environment.etc."nix/path/nixpkgs".source = inputs.nixpkgs; in your configuration.nix somewhere.

This is very similar to what NobbZ did, but will be able to update online because of the indirection through /etc, while NobbZ’s version wants to change the env vars with every nixpkgs update, and env vars don’t really change until a reboot.

Awesome. And just like that it worked.

I have so much to learn. It feels like my ealry days in Linux (Red Hat 5.1). Not really having a clue or understanding, but trying and failing and trying again. I really is fun learning a competely new way of doing things, and a new language, but sometimes it can be so paralyzing and frustrating.

I am so appreciative of the community here. Couldn’t be a more helpful and friendly bunch.

Would you mind having one more look at my flake.nix.

{
  description = "NixOS configuration";

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

  outputs = { nixpkgs, home-manager, ... }@inputs:

  let
    system = "x86_64-linux";
    # pkgs = import nixpkgs {
    #   inherit system;
    #   # config = { allowUnfree = true; };
    # };
    lib = nixpkgs.lib;
    allowUnfreePredicate = pkg: true;

  in {
    homeManagerConfigurations = {
      user = home-manager.lib.homeManagerConfiguration {
        # inherit system pkgs;
        # inherit pkgs;
        pkgs = nixpkgs.legacyPackages.${system};
        modules = [
          ./users/user/home.nix
          {
            home = {
              username = "user";
              homeDirectory = "/home/user";
            };
          }
        ];
      };
    };

    nixosConfigurations = {
      framework = lib.nixosSystem {
        inherit system;
        specialArgs = { inherit inputs; };
        modules = [
          ./system/configuration.nix
        ];
      };
    };
  };
}

Does it look like it is setup properly? Do you see anything I should be doing differently? It is largely based on the video by Wil T from 1.5 years ago.

Can I delete the commented lines?

How do I get Unfree packages working?

I would add a line in your home-manager.lib.homeManagerConfiguration argument attrset like extraSpecialArgs = { inherit inputs; };, so that you can get at your inputs in your home.nix the same way I walked you through doing it in configuration.nix, should you ever need to.

Also, I believe the output that the home-manager cli tool looks for is homeConfigurations, not homeManagerConfigurations.

Yes, you can delete the commented lines.

For unfree packages, you want to configure nixpkgs through the module options for nixos and home-manager, respectively. In either case, set nixpkgs.config.allowUnfree = true; (there at least was, and may still be, a bug in home-manager that requires you to use allowUnfreePredicate instead. I don’t know if it’s fixed because I use hm as a nixos module rather than standalone)

The snippet in question is quite old, and I am wondering where that is even from, as I am indirecting through /etc for quite a while now…

And I assume change the first line in home.nix from:

{ config, pkgs, ... }:

to:

{ config, pkgs, inputs, ... }:

Am I correct?

Well, I tried that but got an error:

error: flake 'path:/home/user/.dotfiles' does not provide attribute 'packages.x86_64-linux.homeManagerConfigurations.user.activationPackage', 'legacyPackages.x86_64-linux.homeManagerConfigurations.user.activationPackage' or 'homeManagerConfigurations.user.activationPackage'

I don’t get an error using homeManagerConfigurations.

Yes, at least whenever you want to use it.

Huh… shows what I know. I don’t use standalone, so that’s old, secondhand information that may have just morphed in my head. Sorry for the misdirect.

If I ever wanted to begin using the unstable channel, would it simply be a matter of changing the following in flake.nix?

{
  description = "NixOS configuration";

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

to:

{
  description = "NixOS configuration";

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

And would changing back be as simple as undoing those edits?

Yes, that and you’d need to do a nix flake update afterward (I think. It might know it needs to update because the input spec has changed, but I’m not sure. Safer to update). (Good that you know you need to change nixpkgs and home-manager together!)
And again, changing back would also require a nix flake update after the change to affect the lockfile.

This puzzles me:

Sure looks like it’s homeConfigurations from the source code.

Are you using some other tool or wrapper script with a different convention than the main home-manager cli tool?

No. At least not that I am aware of.

OK. I guess you were right. I looked into this again, and the script I was using to build my home-manager stuff looked like this:

#!/bin/sh
pushd ~/.dotfiles
nix build .#homeManagerConfigurations.user.activationPackage
./result/activate
popd

I basically followed the example Wil T gave in his 1.5 yo video. Did things change from back then?

So once I changed to homeConfigurations in both flake.nix and my build script, then it ran without error. Good catch.

So, why did it run fine the other way?

Ah, so you weren’t using the home-manager cli tool at all. That explains it.

I don’t believe the home-manager cli tool had flake support at the time, so you had to build the activation package manually, and so there was no standard flake output name to use. People seemed to use homeConfigurations and homeManagerConfigurations about equally. When the official tool got flake support, homeConfigurations ended up as the standard.

The only thing that makes certain flake output names special is that certain tools automatically look under them for things as a convenience factor (that and the nix community as a whole has decided that specific names should be used for consistency across the ecosystem).

So you can make any outputs you like and point nix build at them, and everything works (nix doesn’t actually even know homeConfigurations is special, only the home-manager cli tool knows that).