Using nix today: A usability quagmire

Warning: rant incoming, but I feel like this sort of thing is not uncommon, and I haven’t seen that much progress since I started using nix back in ~late 2020.

Today I wanted to add a package. Specifically, sshfs-fuse.

The first thing to do is of course to find the exact package name with nix search.

nix search sshfs
error: experimental Nix feature 'nix-command' is disabled; use '--extra-experimental-features nix-command' to override

and trying to follow the instructions it gives you just leads you to a dead end:

nix search --extra-experimental-features nix-command --extra-experimental-features flakes sshfs
error: cannot find flake 'flake:sshfs' in the flake registries

Thankfully, Google has my back, and “nixpkgs sshfs” gets me on my way. The package name is “sshfs-fuse” and I add that to my .nixpkgs/darwin-configuration.nix.

$ darwin-rebuild switch
building the system configuration...
error: nixVersions.nix_2_4 has been removed
(use '--show-trace' to show detailed location information)

Well that sucks. It would have been nice if it gave me any kind of inkling of what I’m supposed to do, or even what the current version is.

Googling “error: nixVersions.nix_2_4 has been removed” turns up one bug report (The rnix-lsp from nix-community - GithubHelp) with no solutions. Variations were no immediate help either.

Googling “Nix 2.4” shows a release announcement in November of 2021. So this is being deprecated and going EOL in a year with no replacement being specified!?!?

Googling “nix version” gives me the front page and “NixOS 22.05 released.” Well that’s obviously not it.

Googling “nix current version” gives me the downloads page (Download Nix / NixOS | Nix & NixOS). Ok, so the current version of nix is 2.11.1. I try replacing nix_2_4 with nix_2_11 in my .nixpkgs/darwin-configuration.nix

building the system configuration...
error: attribute 'nix_2_11' missing

       at /Users/spease/.nixpkgs/darwin-configuration.nix:95:17:

           94|   nix.nixPath = [ "darwin=$HOME/.nix-defexpr/channels/darwin" "nixpkgs=$HOME/projects/nixpkgs" ];
           95|   nix.package = pkgs.nix_2_11;
             |                 ^
           96|   nix.extraOptions = ''
(use '--show-trace' to show detailed location information)

Maybe I need to run nix-channel --update?

Nope, same error.

Checking the release notes for 22.05 says that it’s using nix package manager 2.8. Ok, let’s try that.

building the system configuration...
error: attribute 'nix_2_8' missing

       at /Users/spease/.nixpkgs/darwin-configuration.nix:95:17:

           94|   nix.nixPath = [ "darwin=$HOME/.nix-defexpr/channels/darwin" "nixpkgs=$HOME/projects/nixpkgs" ];
           95|   nix.package = pkgs.nix_2_8;
             |                 ^
           96|   nix.extraOptions = ''
(use '--show-trace' to show detailed location information)

I see in one of my google searches there was a nix package search - NixOS Search. Ok, let’s try that…nope, it says 2.8 and 2.11 too. Maybe I need the full version string?

building the system configuration...
error: attribute 'nix_2_8_1' missing

       at /Users/spease/.nixpkgs/darwin-configuration.nix:95:17:

           94|   nix.nixPath = [ "darwin=$HOME/.nix-defexpr/channels/darwin" "nixpkgs=$HOME/projects/nixpkgs" ];
           95|   nix.package = pkgs.nix_2_8_1;
             |                 ^
           96|   nix.extraOptions = ''
(use '--show-trace' to show detailed location information)

Ok, let’s try just pkgs.nix:

building the system configuration...
trace: warning: The option `users.nix.configureBuildUsers' defined in `/Users/spease/.nixpkgs/darwin-configuration.nix' has been renamed to `nix.configureBuildUsers'.
error: attribute 'installApplication' missing

       at /Users/spease/.nixpkgs/overlays/carthage.nix:3:1:

            2|
            3| darwin.installApplication rec {
             | ^
            4|   pname = "carthage";
(use '--show-trace' to show detailed location information)

Well, it accepts that, but now my overlays seem to be broken. I vaguely recall running into this issue - and apparently nobody who saw my post knew how to fix it.

So it looks like I’m stuck with potentially hours or days of troubleshooting to fix that error, or implicitly removing all those applications.

Attempting to move things out of the darwin namespace to the top-level and renaming installApplication to darwinInstallApplication, I get a couple more obvious error messages. Then I get:

building the system configuration...
error: value is a string while a list was expected

       at /nix/store/qwg6sqp8vy46mc3i4p90f51snfs7laxi-nixpkgs-22.11pre415372.7b06206fa24/nixpkgs/lib/lists.nix:36:20:

           35|   */
           36|   forEach = xs: f: map f xs;
             |                    ^
           37|
(use '--show-trace' to show detailed location information)

Showing a trace generates pages of low-level error messages. I have no clue what’s going on. Is it something to do with forEach changing? Is it an issue with the maintainers field of one of the packages using installApplication? I don’t see any packages listed. Is it because something thinks darwinInstallApplication is a derivation rather than a derivation-maker? That’s my best guess.

At this point I’m just fed up. All I wanted to do was add one package to my system, and instead I got bogged down in fixing an override. The process of adding overrides is unreasonably complicated (There are at least 4 functions, not counting language-specific ones, none of which seemed to work for adding a package to the darwin namespace, and it would seem that things are too complex and the experts are too few.

Is nix supposed to be just generally unusable and not targeted at people if you aren’t developing nixpkgs? Because the goals sound great, but I’ve been trying to use it for years, and it seems like the usability issues for even basic use never stop. And the level of knowledge required to maintain even a basic system and work around eg missing binary packages is apparently far beyond what I would consider the “casual user whose life doesn’t revolve around nix” level.

To preemptively address the objection that my installApplication derivation isn’t “basic use” - I’d say that’s correct, but it also seemed necessary given that several common applications eg firefox couldn’t be installed with nix on macOS. Since the level of knowledge required to create a nix derivation was well in excess of that for homebrew, I figured I would make something that would make it simpler. However, it broke before I could try to upstream it, and I simply haven’t had the massive amount of time nix seems to require to do anything meaningful with it to fix it.

Having declarative package management sounds great, but the current expression of it just has far too many edge cases (“the exception is the rule”) and the practical steps required to do things is just too complex to remember, and the underlying implementation concepts somewhat intuitive with what’s actually being expressed. Eg you’re describing a package, but it’s actually a function, and because of that you can’t just “override” by setting the variables of that package. You have to use more function calls, and know when to use which override function call, and now the simplicity of the language is lost in the complexity of the API.

7 Likes

It seems to me that many of your issues here stem from misaligned expectations.

For example, nix search is a tool mainly meant for searching a package in a flake. It is a bit unfortunate that nix search regex cannot just search Nixpkgs when that is what a majority of uses will want but that is a trade off that was chosen to make the command consistent with all other new nix subcommands. That is IMO a clear improvement over implicit Nixpkgs-specificity of nix-env. Just running nix search --help would show you a proper usage: nix search nixpkgs sshfs

That page is a SEO farm or something. If you follow the link to the actual issue, you will find that it has been resolved by Unpin the version of Nix used as a checkInput by mtoohey31 · Pull Request #93 · nix-community/rnix-lsp · GitHub. A similar fix would work for you.

Ideally, Nix would be able to produce an error message that would display the location info like when a non-existent attribute is used but that is not currently possible. While it has improved since 2020, error messages are still one of Nix’s weakest points.

You make a correct inference that your Nixpkgs revision is too old and update it but rather than trying to guess a package name, you should again try to use a package search, as you do next. You just need to notice that the package name is just nix (or nixVersions.nix_2_9 for the specific minor version). If you click ▾▾▾ Show more package details ▾▾▾, it will even tell you the configuration snippet.

Here you can see how the errors improved compared to the last time :wink:

See the other thread for my suggestion.

That means the xs argument to map (and thus also forEach) is string where it should be a list. Without seeing the trace, it is really impossible to tell where the error occurs.

There was an attempt at bringing a proper type system to Nix that might have helped improve the error messages for wrong argument types but it fizzled out. The focus is now on Nickel so it will probably be a while until we see its fruit in Nixpkgs.

The one you want for darwin is overrideScope', which is not even on that list. There is a proposal to unify the overriding function for derivations so at least that part should get simpler eventually.

It’s not supposed to be but once you slightly wander off the beaten track, it often is. Especially on lower tier platforms like MacOS. Once you need to override anything or use some functions, you are faced with a weird functional language and often not well documented Nixpkgs internals.

People are trying to improve it (e.g. Flakes) but you are still best of having access to someone who can navigate the maze, if you want to have a relatively painless journey. Nix community is very helpful but questions still get lost in the stream.

20 Likes

Had a little more time tonight. The issue with installApplication was that some of the “maintainers” in my local overlays had a list, and some didn’t. At first it complained about string instead of list - this was because installApplication lets you specify with a string to simplify the syntax of the derivations based on it. Once I fixed that, some regular derivations were using the maintainers.username syntax and the error changed to “set instead of list”. I don’t recall seeing the actual end derivation in the error, but it was quite lengthy and I may have simply missed it. If I have some more time I may try to reproduce the exact error.

I would recommend just passing the meta as is instead of creating shortcuts like this. You do not save much and it will just be confusing for anyone familiar with Nixpkgs conventions, especially if this is supposed to be merged to Nixpkgs.

1 Like

Minimizing the knowledge of nix required was actually the goal for this. I was modeling it after Homebrew cask files. My reasoning was that the barrier to entry to create a nix derivation is relatively high compared to a brew cask file - there’s just more going on. And for applications with a .dmg, you may not need a more complex build process other than downloading it and moving it.

So this is scoped to the case of an easy-to-install application. If it’s more complex than that, there’s no getting around someone needing more knowledge of nix. But otherwise the goal was minimum knowledge - and exposing meta requires someone to understand and remember the “with” syntax, and what it’s doing.

For example:

{ darwin }:

darwin.installApplication rec {
  pname = "mountain-duck";
  version = "4.9.0.18884";

  url = "https://dist.mountainduck.io/Mountain%20Duck-${version}.zip";
  sha256 = "l4eFm5CxqVCeJZ4B2rLx57y4tlB5gI/E+nvfH4Ql92I=";

  description = "Lets you mount network storage as a disk";
  homepage = "https://mountainduck.io/";
  license = "unfree";
  maintainers = [ "spease" ];
}

That’s it. That’s all you need to install an application. There’s barely any boilerplate or syntax to remember, but it’s also still using the nix language directly.

2 Likes