NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.14k stars 1.47k forks source link

have `nix flake init` generate the inputs too #7005

Open teto opened 2 years ago

teto commented 2 years ago

I am a huge fan of flakes that solve 80% of the issues I have with the nix ecosystem. One decision eludes me though, flakes are pure by default, yet it defaults to use-registries = true and nix flake init generates:

{
  description = "A very basic flake";

  outputs = { self, nixpkgs }: {

    packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;

    defaultPackage.x86_64-linux = self.packages.x86_64-linux.hello;

  };
}

Wouldn't it be more reproducible to specify the inputs and more intuitive (else a newcomer may wonder where nixpkgs come from) ? also it serves as a better example.

  inputs = {
    nixpkgs.url = {      url = "github:nixos/nixpkgs/nixos-22.05";  };
};

I am sure this was discussed before so I would be happy wih a link towards the justification.

thufschmitt commented 2 years ago

(I think that issue should rather belong to NixOS/templates. @domenkozar can you move it?)

I am sure this was discussed before so I would be happy wih a link towards the justification.

I don't think it has been discussed publicly.

I'm not the author, but I guess one of the reasons is that it plays very nicely when making quick experiments: running nix build on a freshly nix flake new-created flake will reuse nixpkgs from my registry so it won't have to re-fetch several hundred MBs just to get hello.

That being said, I agree that it's pushing towards an arguably bad pattern, so I wouldn't mind having it use a more well-defined input.

teto commented 2 years ago

(I think that issue should rather belong to NixOS/templates. Anyone with the right amount of power, can you move it?)

while it fits nixos/templates, there is the broader issue of do we want use-registries = true by default.

It seems like we removed impure aspects of legacy nix to replace it with another source. It seems reasonibly easy to explain/document: "by default you have a flake that works all the time, but if you want to spare some bandwidth/CPU, you can try nix build --override-input nixpkgs github:nixos/nixpkgs/nixos-22.05 with the hope it works" Sounds easier to explain than the opposite to me at least: "so by default we have no guarantee about that flake, but if you find a working nixpkgs for it, you can enforce it with nix build --override-input nixpkgs github:nixos/nixpkgs/nixos-22.05 .

mtalexan commented 1 year ago

There's been extensive discussion over on the https://discourse.nixos.org about how inputs for flake.nix files should be used. The baseline consensus seems to be that because a flake.lock is generated on first use, which "pins" all inputs to exact revisions, it's a very exceptional case where you'd want to list the specific revision in your flake.nix inputs. Given that intention, there's really no reason for the default trivial template oto list a specific nixpkgs version rather than waiting for the flake.lock to pin it.

teto commented 1 year ago

There's been extensive discussion over on the discourse.nixos.org

If you have a specific discussion in mind, it's welcome.

it's a very exceptional case where you'd want to list the specific revision in your flake.nix

This is not what I worry about, it's the "magical" aspect of it, with an hidden input/global state, unlike the functional paradigm of nixos. I can understand we use the registry as aliases because it's easier to write nix run nixpkgs#... then nix run github:nixos/nixos-unstable#... but in a flake, that obfuscation is unncessary. The flake should be optimized for reading.

teto commented 1 year ago

@mtalexan basically my beef with the registry: https://github.com/NixOS/nix/issues/7422#issuecomment-1341508027

Bookmarking for my future self: https://github.com/NixOS/nixpkgs/issues/204292

mtalexan commented 1 year ago

You mention, but seem to discount, the fact that the registry is layered and allows you to override the prior levels. The only explicit examples I've seen online are for picking a specific nixpkgs version, but the case that popped immediately to mind for me is actually github:.

If I'm running a CI pipeline, many times I explicitly don't have internet access from that pipeline since I need to guarantee reproducibility even if some GitHub user decides to remove their flake repo in a couple years. Instead, I mirror all the repos I need to a private server and only allow the pipeline to access that. Such a case is common for certain industries nix caters to, and perfect for using the registry to redefine the github indirect reference to instead go to the internal server (not possible yet, but presumably will be before nix3 release). Alternatively, I can go thru every flake reference individually and redefine the registry entry for it to point to some fully qualified path (every flake is also registered in the global registry using the name and URL given to it in the flake.nix on first use).

Say for example a flake.nix lists

inputs.a-flake.url="github:someuser/repo";

The first time this is used it's added to the global registry as

flake:a-flake github:someuser/repo

If someuser takes down their repo, I can fix it in the system registry by overriding a-flake without changing any flake.nix files, so I don't have to fork a b-flake I rely on that is still on GitHub but not yet updated to point to a new fork.

Or if I instead forked their repo to add some changes and want to test my version (without affecting anyone else on the system), I can override a-flake at a user level.

The very point of the registry is exactly what you're saying you don't like: to be able to adjust the source of external components pulled from flake.nix files that may or may not be under your direct control. There are tons of examples of this being necessary for development and long term support, and I'm sure I've seen some in the community complaining about allowing external dependencies at all for some of these same reasons.

My only concerns with the registry right now are:

  1. All flake inputs effectively share a single global namespace in the registry that's populated by the "independent" flake.nix files
  2. Templatized indirect references like github: can't be defined in registry config files (they're hardcoded in the code only)
teto commented 4 months ago

Having the behavior you describe baked-in looks misleading and overkill: we have inputAbut we can make A become B implicitly. You can do the same with --override-input input path-to-source.