Nix-direnv using old nix version -> flakes not working

I’m using a main flake that applies both my system config and my HM config (similar to the structure of gvolpe’s nix config).

In both configs I use an unstable argument that imports github:NixOS/nixpkgs/nixos-unstable and have defined nix = { package = unstable.nixFlakes; ... };

Both as user and root I (correctly) get:

> nix --version
nix (Nix) 2.8.0
> which nix
/run/current-system/sw/bin/nix

However, when trying to use nix-direnv according to the instructions, it appears direnv tries to execute the “stable” version of nix:

direnv: using flake .nix/ --impure
error: 'print-dev-env' is not a recognised command
Try '/nix/store/93p5wvnxngf7xi1xq5agrs61amsy0fp4-nix-2.3.16/bin/nix --help' for more information.
error: 'flake' is not a recognised command
Try '/nix/store/93p5wvnxngf7xi1xq5agrs61amsy0fp4-nix-2.3.16/bin/nix --help' for more information.

(Come to think of it, direnv without flakes already gave me warnings about experimental-features not being a valid flag, which would also point to direnv using a wrong nix version).

How do I ensure that all modules actually use the same (and intended) nix derivation throughout my system?

Are you sure you are installing nix-direnv from unstable and not from 21.11? And what way of installation did you acutally use? The recommended HM way? Or the nixos config way? Or another?

For HM I have to say, that on 21.11 you need to enable flake support manually, while it is enabled by default when using an unstable from December or January. I never installed through system config or any other means than HM though, therefore I can not say much if you are not using HM.

@NobbZ Ah, you may be on to something… I am using HM, but indeed my “base-HM” is 21.11 and I’m overriding with unstable as needed. But indeed, while I have nix.package = unstable.nixFlakes in both system and home, there is no programs.direnv.package attribute I can use to override that one. Would that mean I have to do that as an attribute override to force the version of nix-direnv itself too? What would that look like?

To enable flake support on HM 21.11 for nix-direnv you need to set programs.direnv.nix-direnv.enableFlakes.

It will then use nix_2_4 from the 21.11 branch.

If you wan’t to use another nix for that, you need to use an overlay that replaces the nix-direnv attribute. I had to look up what exactly need to be overriden with what for 21.11… Though I think it would be at least the nix argument.

PS: I don’t think you should use nixFlakes as you are on unstable already for the system. Instead just use nix! On unstable nix is guaranteed to be 2.4 or newer and therefore can have flakes enabled. You just need to remember to actually enable the appropriate experimental features.

I did have that set at first:

    direnv = {
      enable = true;
      nix-direnv.enable = true;
      nix-direnv.enableFlakes = true; # default
    };

but my HM derivation failed to build with:

       Failed assertions:
       - The option definition `programs.direnv.nix-direnv.enableFlakes' in `<unknown-file>' no longer has any effect; please remove it.
       Flake support is now always enabled.

So if I understand correctly I have to override pkgs.nix-direnv on the “overlay level” so that the HM-module takes the unstable one? Or (maybe nicer?), can I do that override “in-line” in the direnv = {} definition?

As for nix vs nixFlakes: point well taken, the docs are a bit unclear due to overlapping histories I suppose.

This means you are using HM from master. You really shouldn’t mix a master HM with stable nixpkgs, this is known to cause arbitrary malfunctions.

Now I’m getting confused (more) confused: in my main flake I have:

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
    nixpkgsUnstable = {
      url = "github:NixOS/nixpkgs/nixos-unstable";
    };

    nurpkgs = {
      url = github:nix-community/NUR;
      inputs.nixpkgs.follows = "nixpkgs";
    };

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

...

  outputs = inputs @ { self, nixpkgs, nurpkgs, nixpkgsUnstable, musnix, home-manager }:
    let
      system = "x86_64-linux";
      # hostname = builtins.readFile /etc/hostname;
    in
    {
      homeConfigurations = (
        import ./outputs/home-conf.nix {
          inherit system;
          inherit (inputs) nixpkgs nurpkgs nixpkgsUnstable home-manager;
        }
      );
...

Doesn’t the “follow” mean that my HM should take the same version as the nixpkgs one?

home-conf.nix reads:

{ system, nixpkgs, nurpkgs, nixpkgsUnstable, home-manager, ... }:

let
  mkHome = username: hostname: (
    let
      homeDirectory = "/home/${username}"; # TODO: if darwin then /Users/${username}
      configHome = "${homeDirectory}/.config";

      pkgs = import nixpkgs {
        inherit system;

        config.allowUnfree = true;
        config.android_sdk.accept_license = true;
        config.xdg.configHome = configHome;

        overlays = [
          nurpkgs.overlay
        ] ++ (import ../home/${username}/overlays)
          ++ (import ../system/overlays);
      };

      unstable = import nixpkgsUnstable {
        inherit system;
        config.allowUnfree = true;
        config.android_sdk.accept_license = true;
        config.xdg.configHome = configHome;
      };

      nur = import nurpkgs {
        inherit pkgs;
        nurpkgs = pkgs;
      };

      conf = (
        import ../home/${username}/home.nix {
        inherit nur pkgs unstable username hostname homeDirectory;
        inherit (pkgs) config lib stdenv;
      });
    in
    home-manager.lib.homeManagerConfiguration rec {
      inherit pkgs system username homeDirectory;
      extraSpecialArgs = { inherit unstable; };
      stateVersion = "21.11";
      configuration = conf;
    });
in
{
  "jeroen@jspectre" = mkHome "jeroen" "jspectre";
  "jeroen@jnixryz" = mkHome "jeroen" "jnixryz";
}

No, that means that the nixpkgs used in HM is the same as nixpkgs, the url = github:nix-community/home-manager doesn’t specify any branch, so master is used.

Your users config clearly uses whatever gets passed in as nixpkgs, which in your case is the release 21.11.

The version of HM you use is therefore not getting what it expects. It is not guaranteed to work with that. Either specify an appropriate release branch for HM (github:nix-community/home-manager/release-21.11 IIRC) or use unstable nixpkgs with it.

Ah so much for a huge misunderstanding on my part!

However, changing to

    nixpkgsUnstable.url = "github:NixOS/nixpkgs/nixos-unstable";

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

still gives me stable in HM, judging from the fact that the HM generation still links to (stable) nix-direnv-1.5.0

The pkgs you pass into the HM call is what gets used.

So that would mean that

  • home-manager = { ....follows = "...."; } does nothing?
  • If I want to make HM use unstable for its modules and internally, I have to override pkgs with unstable in the HM call, which means I would have to reverse everything else under home.nix where I want to “just” use stable packages, like e.g. for home.packages

It’s starting to make sense now, though TBH it’s more convoluted than I’d have expected. It begs the question whether HM shouldn’t provide a package attribute for all its modules to be able to explicitly choose…

No. It sets the nixpkgs that is used by HM when using functions from nixpkgs. Actually it is discouraged by the HM team to use follows here unless one has very specific reasons.

Yes.

It definitely should, as well as nixos should, though we are not there yet. The *,package idiom is relatively new and I think it will take a while until everything is written in a way that is able to use such a thing, or might never happen for stuff that isn’t used regularly enough.

1 Like

Thanks, very informative and enlightening again :smiley:
I guess this is again a nice example where I “cargo-culted” my way through a complex generic (multi-host/multi-user) config flake and what comes of it… Let’s call it “learning by doing” :grin:

Just noting that it is also worth adding home.enableNixpkgsReleaseCheck = true to your home manager config so that you’ll get an error if the versions ever get out of sync in the future.

You can see some more discussion in this GH issue: use flake: [print-dev-env | flake] is not a recognized command (NixOS) · Issue #137 · nix-community/nix-direnv · GitHub

1 Like