Flakes/Nix3.0 issues

Hi all, this thread is inspired by Improving flakes - #11 by nrdxp, lets try to list design issues or changes that you guys would like to see with flakes/Nix3.0

Here is my list, most of it is just improvements according to my fetishes :wink:

General ergonomics and UX improvements

  1. Partially merge flake-utils:
  • eachSystem
  • Expose tier1/tier2/tierX systems support as arrays to be used as such nixpkgs.lib.eachSystem nixpkgs.lib.systems.tier1 or something similar
  • check-utils - Maybe not a ā€˜mustā€™ but I quite like it :slight_smile:
  • filterPackages and flattenTree would be nice.
  1. Partial devShell implementation
  2. flake.nix output changes:
  • lib.<name> output. Where name evaluates to a function or attrset which looks something like this:
lib.add = { 
    function = a: b: a + b;
    description = "Adds arguments"; 
    docs = ''
        The addition of two whole numbers results in the total amount or sum of those values combined. The example in the adjacent image shows a combination of three apples and two apples, making a total of five apples. This observation is equivalent to the mathematical expression "3 + 2 = 5" (that is, "3 plus 2 is equal to 5").
    '';
};
  1. nixosModules and similar should be namespaced to something like modules.<name>. This would allow to have something like: modules.nixos, modules.darwin , modules.home , modules.customOptions , modules.suites
  2. Would be nice to see NixOS modules system to get a description argument (This way we could present it in nix flake show)
  3. nixosConfigurations.<hostname> evaluates to system architecture specific module. I think it would make more sense to change its definition to nixosConfigurations.<system>.<hostname>
  4. If there are disagreements about point #6 - maybe nixosConfigurations should be moved under modules.nixos namespace mentioned in #4?
  5. defaultPackage and similar attributes should be moved to packages.<system>.default
  6. legacyPackages should be replaced with packages and something similar to flake-utils.lib.flattenTree. Tho, this might have a large impact on evaluation performance.
  7. inputs.<name>.sourceInfo should include more information like repository name and owner
  8. Extra CLI commands would be nice like nix fmt, nix info nixpkgs#bash, nix tree -> https://github.com/utdemir/nix-tree
  9. Support flake references to patches Ā· Issue #3920 Ā· NixOS/nix Ā· GitHub

Brainstorming

  1. Location of nix registry and system configuration should be moved under /nix folder since these days /etc basically is ā€˜immutable global system configurationsā€™
  2. Registry sources (git repos) should be symlinked to /nix/registry/sources
  3. apps vs packages - the difference between these two is that apps can not be built or installed as easily and are used only by nix run. (nix run abc#xyz currently checks apps.xyz ā†’ packages.xyz ā†’ legacyPackages.xyz)
    I am thinking that maybe apps should be removed or maybe represent devshell (like nix shell -c xyz) since packages can be executed anyways. The end result should be something like "If explicitly defined runnable exists in devshell - use it, otherwise default to packages.xyz.
    TL;DR: I am not a fan of apps and packages separation but I am not sure whats the solution is here nor how itā€™s supposed to work.
7 Likes

Brainstorming alert:
So I was thinking about apps thing, since Iā€™m not a fan that it basically represents packages in a different namespace.
I feel like its a super odd API but something like this would be interesting:

outputs = { nixpkgs }:{
  devshell.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.mkShell { 
    runnables = {
      xyz = nixpkgs.legacyPackages.x86_64-linux.xyz;
    };
 }) ; 
}

this way xyz would be part of devshell and nix run .#xyz could evaluate outputs.devshell.x86_64-linux.runnables.xyz.
If nix run does not find such attribute in devshell - evaluate outputs.packages.x86_64-linux.xyz

TL;DR: This way nix run functions the same way as we are used to + you can create a custom builder so you could add defined apps as part of devshell.

Downsides:

  • Weird API
  • One may think that apps are started from devshell when they are not (or maybe they should be started from devshell?)

One may argue that what Iā€™m looking for is namespaced package sets (like packages.<system>.<pkgsetName>.<name>) but at that point, we are reimplementing legacyPackages for better or for worse

Definitely not saying that any of this is a way to go, just a couple of thoughts.

Personally I agree with some points here:

  • Lets add lib and make us able to give descriptions and docs to a function, perhaps we can re-use the __functor-idiom?
  • Lets add a way to add short descriptions to modules, configurations and apps or any other output that currently gets just a constant description on nix flake show (modules could get meta.description or meta.title, apps could get a description or title, etc)

I do not agree though with the following:

  • Rename *Modules to modules.*, instead provide a way to keep them flat as nixosModules, darwinModules, homeModules or whatever else might follow, by giving an interface that allows us to declare custom attributes with types.
  • Renaming of default* to *.$system.default, instead Iā€™d prefer using the default prefix more consistently: defaultNixosModules, devaultDevShell, etc.
  • Removal/flattening of legacyPackages. Please instead give a way to properly nest packagesets in packages, but keep legacyPackages as legacyPackages in nixpkgs up until the point when really there is not a single function, not even builders and fetchers left in it, but really only nested package sets.
  • Also I strictly disagree with removal of apps. They are fine as they are, leaving them in doesnā€™t hurt anyone who doesnā€™t use them, but removing them hurts those who do.
1 Like
  • Rename *Modules to modules.* , instead provide a way to keep them flat as nixosModules , darwinModules , homeModules or whatever else might follow, by giving an interface that allows us to declare custom attributes with types.

Yeah, that would be an ideal option, unfortunately, I donā€™t see how does one implement it in a sane usable manner. It is very possible that Iā€™m just not smart enough for that

  • Renaming of default* to *.$system.default , instead Iā€™d prefer using the default prefix more consistently: defaultNixosModules , devaultDevShell , etc.

Consistency is what Iā€™m looking for, Iā€™m fine with both options itā€™s just that Iā€™d prefer my option since all same type (ā€˜typeā€™ in terms of ā€˜packageā€™, ā€˜appā€™, ā€˜overlayā€™, ā€˜devshellā€™) of attributes are under the same namespace.

  • Removal/flattening of legacyPackages . Please instead give a way to properly nest packagesets in packages , but keep legacyPackages as legacyPackages in nixpkgs up until the point when really there is not a single function, not even builders and fetchers left in it, but really only nested package sets.

Yeah, I believe that flattening is required due to performance reasons and the amount of packages there are. Please correct me if Iā€™m wrong.

  • Also I strictly disagree with removal of apps. They are fine as they are, leaving them in doesnā€™t hurt anyone who doesnā€™t use them, but removing them hurts those who do.

From my point of view apps arenā€™t doing much since packages and devshell exist. Since I have not thought of a solution that Iā€™d be happy with - I am NOT recommending the removal of apps, just asking to brainstorm to see if we can do better

The problem I see with your way, what happens when someone actually wants to package something under the attribute name default?

Having self for the current flake, while there is also a pkgs.self trips me up regularly when I use callPackage and forget to pass in self explicitely, similar could happen with your proposal.

Yeah, this makes default a reserved word. I just see it as a cleaner option compared to alternatives.
Of course, word itself does not matter, one could call it _default or something but thatā€™s just pushing the edge case further to the edges.

As noted in the first message - these are just my thoughts/ideas based on my fetishes, I am just throwing this all out here to see if I find other like-minded individuals or maybe some other better ideas will come out of this :smiley: (Tho, I expected to see more people posting what they themselves think that can be improved :confused: I guess we will see how its going to go, its been just few hours)

1 Like

I know @blaggacao has been recently pushing for some kind of json schema validation for Nix. Something like a builtins.validateJSONSchema. If something like this does catch on, we could use a json schema to define what the flake can output. As a bonus, since we now control the schema ourselves, we can make Nix error instead of just warn if the schema is broken.

2 Likes
1 Like

( Any feedback on that PR is very appreciated :grin: )

2 Likes

After using flakes for a month or two, here are my annoyances as an end user:

  1. While there is nice support with flakes for building on different systems (x86_64-linux, aarch64-linux, etc), there is no built-in support for cross-compiling, or easily specifying the system you want to cross-compile to.

    [flakes] Where do cross compiled packages go? Ā· Issue #5157 Ā· NixOS/nix Ā· GitHub

    At work we worked around this by specifying both native packages and cross compiled packages as different packages exposed by our flake, but it feels somewhat hacky.

  2. There is no good way to pass options to flakes: Passing options to flakes

    This seems like a really big blow to usability. Judging from that thread, it seems like passing options to nix-build is a relatively common thing to do.

  3. The nix registry stuff seems like it is nice, but by default it doesnā€™t pin nixpkgs to a specific commit (or even a Hydra channel). This means if you do something like nix shell nixpkgs#foo, it is possible you have to build from source, and you may just have to download the latest Nixpkgs master every time.

    I created a thread explaining how to pin to a commit on one of the channels, but I feel like something like this should be done by default: How to pin nix registry nixpkgs to release channel

  4. nix flake show doesnā€™t handle IFD in a graceful way: Don't allow IFD in flakes by default by edolstra Ā· Pull Request #5253 Ā· NixOS/nix Ā· GitHub

    Instead of immediately failing out when reaching IFD, it would be great if nix flake show instead displayed an error message only for those attributes that require IFD, but continued on showing the rest of the attributes defined in the flake.

8 Likes

nix flake show handles any error it encounters this way. It just fails. So you are totally right, instead of printing errors about unexpected things it should warn properly.

Instead of ā€œexpected derivationā€ (without even telling what attribute it is currently evaluating) it could display the attribute in red and instead of name/description it could write out the warning/error it encounteredā€¦

3 Likes

Just stumbled over another oneā€¦

nix edit should really be renamed. It does not allow editing at all! cat, less or maybe page would be so much better options for that subcommands nameā€¦

If nix edit is to be kept, it should really make sure that what ever is opened is not in the store! Even if I do nix edit .#foo it will copy . to the store first and then open my editor on the file from the storeā€¦

edit

Opened an issue for this: flakes: `nix edit` does not actually allow to edit the opened file Ā· Issue #5417 Ā· NixOS/nix Ā· GitHub

4 Likes

Hereā€™s another annoyance I forgot about originally:

The nix shell command doesnā€™t set the environment variable IN_NIX_SHELL: Set `IN_NIX_SHELL` or similar for `nix shell` Ā· Issue #3862 Ā· NixOS/nix Ā· GitHub

As an end-user, it is somewhat unfortunate that this issue was closed unilaterally, despite there appearing to be a lot of support for it being fixed.

4 Likes

I agree with this general perception, but I think this is an issue of people talking past each other? I suspect there needs to be some other mechanism than IN_NIX_SHELL that can more granularly reflect the conditions? Iā€™ve wondered if maybe just NIX_COMMAND=<invocation> would suffice, but I havenā€™t tried to survey how people are using IN_NIX_SHELL to understand it.

2 Likes

I think most people are using $IN_NIX_SHELL to customize their shell prompt

2 Likes

This is what I assume, since it is how I use it. I get the impression that the objections are about avoiding overloading the semantics of the env and stuff like Set `IN_NIX_SHELL` or similar for `nix shell` Ā· Issue #3862 Ā· NixOS/nix Ā· GitHub.

Assuming the latter is solved by clearing any such envs from the build environment, it seems like an env reflecting the invocation in all of the ~subshell-creating-commands would defuse the semantics concern, and avoid needing a new env for each distinct semantic. (with the downside of not being able to preserve an old env for backwards compact if a command is renamed?)