Live data from Hacker News

Why did Nix adopt Flakes?

jetpack.io

51–60 of 68 posts

Re: Why did Nix adopt Flakes?

#51
post #36

Am I the only one completely confused by the examples that appear to put command line arguments after shell end-of-line comments? Is that not a typical shell? example: nix run .#cowsay -- flakes are neat Some explanation of what the heck this means would be really useful.

"--" isn't anything special in a typical shell. It's just another argument, one that customarily means "pass the rest of arguments on to a subprocess". Or are you confused about the "#"? It doesn't start a comment in the middle of a token.

> one that customarily means "pass the rest of arguments on to a subprocess".

It's convenient for passing options and args to a subprocess, but it customarily means "don't interpret anything following this as a short or long option, just as a positional argument". For example:

  touch -f     # error
  touch -- -f  # creates a file named "-f"
  rm *         # oh crap we just passed "rm -f" a bunch of files
  rm -- *      # don't treat that "-f" as an option, just delete the file named "-f"

Re: Why did Nix adopt Flakes?

#52
post #31

Earlier quoted context omitted.

I think it only lazily copies files that are referenced by your nix expression. I tested this branch, and a flake-based shell launched in 3 seconds inside a large monorepo (vs 30 seconds before). I don't think it is possible to copy this repo in 3 seconds.

I hope that helps with nixpkgs repo as this takes a lot of time whenever it is updated.

I don't think it will. There isn't any good way to incrementally fetch remote nix files, so to use nixpkgs it all has to be downloaded and unpacked.

Re: Why did Nix adopt Flakes?

#53
post #27

Earlier quoted context omitted.

> It's a package spec, just like debian/* and rpm/*.spec. No. It's not. The interface that Nixpkgs' callPackage expects to find in default.nix within the Nixpkgs source tree is (kinda) like an RPM spec or Debian control file and friends, but that's not what flakes are. Flakes is mostly about providing mechanisms for distributing and referring to code written in the Nix language, and in that way facilitates the mainte…

>Flakes [...] facilitates the maintenance of 'out-of-tree' (read: not in Nixpkgs) Nix packages. Yes, aka a Nix package spec. >But flakes can also be (and are) used to ship Nixlang libraries, end user configurations, IaC for clusters or fleets of servers, overlays of packages to be composed with an end user's copy of Nixpkgs, etc. Yes, just like DEB / RPM packages. >A flake doesn't have to contain any packages at all.…

> > Flakes [...] facilitates the maintenance of 'out-of-tree' (read: not in Nixpkgs) Nix packages.

> Yes, aka a Nix package spec.

Right... one of things that flakes can be used to distribute is roughly comparable to an RPM spec. That is not the same thing as being an RPM spec. A BitTorrent magnet link used to distribute an MP3 file is not itself an MP3 file, either.

> > But flakes can also be (and are) used to ship Nixlang libraries, end user configurations, IaC for clusters or fleets of servers, overlays of packages to be composed with an end user's copy of Nixpkgs, etc.

> Yes, just like DEB / RPM packages.

There is a sense in which flakes and RPMs can (sort of) be used to achieve the same things here, but not remotely in a way 'just like' each other. A flake.nix file is not an archive, and an RPM is not a configuration file format for something like Puppet. The latter point is so obvious that I have to assume you're being deliberately obtuse here.

> > A flake doesn't have to contain any packages at all. And when it does contain a package, the package is always defined with reference to some other package collection that it pulls its dependencies from (almost always Nixpkgs)

> Yes, what DEB / RPM call meta-packages.

No. RPM and DEB metapackages are 'abuses' of an archive format for either (a) just distributing install-time hooks and activating triggers or (b) forcing the installation of actual packages through the normal mechanisms of declaring dependencies on them.

Nix has no equivalent to (a) because 'installation' doesn't mean the same thing with Nix and hooks and triggers are owned by Nix profile managers rather than packages.

If Nix has anything equivalent to (b) in the RPM and DEB worlds, it's this¹ which has nothing to do with flakes and is certainly not equivalent to a flake with no packages declared. In fact, any flake used to distribute such a buildEnv-based metapackage would have to declare it as a package.

A flake without any packages declared is not an archive of a Nix package whose data is empty but whose metadata is present.

Idk what to tell you. Clearly you are trying to somehow 'demystify' Nix terms by equating their referents to things that are familiar to you and others, but your desire for succinctness here pushes you to elide basic differences— not just with respect to Nix but with respect to source-based package management in general. Just like with two natural languages, it's simply not the case that every term here has a 1:1 translation.

--

1: https://nixos.wiki/wiki/FAQ#How_can_I_manage_software_with_n...

Re: Why did Nix adopt Flakes?

#54

I find the default way to work with nixos to be a lot easier to use compared to flakes. I am sure flakes are great and all but as with everything nix you can't just integrate it into your normal flow, you have to jump all in with it. I don't think that is a positive.

> I am sure flakes are great and all but as with everything nix you can't just integrate it into your normal flow, you have to jump all in with it.

AFAIR, the only irreversible impact is switching from `nix-env --install` to `nix profile install`.

With repositories, you can add a flake.nix, and still use nix-build or nix-shell however you did before. e.g. You can have the flake.nix import the default.nix or shell.nix code.

Re: Why did Nix adopt Flakes?

#55
post #5

This is a bit of a unnecessarily provocative title, since the question of whether or not to promote the 'experimental' flakes system and replace the channels mechanism is still an active and controversial one in the Nix community. There hasn't been any significant news on this front recently; this article simply explains why flakes were introduced as an experimental feature.

I'm curious what you would change the title to so that you perceive it to be less provocative? In my (disclosure: not engaged in the community much at all) opinion the provocation here is simply because the topic touches on a controversial issue.

Maybe the "Why did ...?" can come across as confrontational. -- If something's good, you're less likely to ask "why do that?".

"What Nix Flakes Solve" or "Benefits of Nix Flakes" would avoid that.

But, I didn't read the title as provocative.

Re: Why did Nix adopt Flakes?

#56
post #46

I’m surprised all of these systems combine build logic and dependency graphs in the same config. It seems like flake might be a step in understanding these things are only tangentially related. I would like to see composability of graphs (and other set operations on binary package repos) integrated into more dependency management systems. FreeBSD is my server of choice and I’d love to say: create a package repo with…

I don't fully understand what you are saying, and I don't know what systems you're including in "all". The system you describe building is exactly what nix does, as well as debian, El, and Arch. Their spec files describe both build and runtime dependices, and installing the package does not install things like Make. Nix goes a little bit further by only including runtime dependices that it can find it the build outpu…

RPM rspecs, port Makefiles, Maven, etc. do not just define package dependencies (build, runtime, etc.) and artifacts, they also have to intimately understand how to patch, build, and package the artifacts. Making the build and package system separate from the dependency management separates concerns and allows the ability for a completely declarative “dumb” dependency graph that can be reasoned about without dealing with build logic that must be executed.

This also allows build processes to evolve without affecting the public dependency graph. This makes it easier to show dependencies are modeled and exposed correctly and makes build logic private to consumers.

Re: Why did Nix adopt Flakes?

#57
I think the second point (nix flakes avoid 'stateful' channels) is the more compelling one. I don't recall an easy way for ensuring channels on different systems pointed to the same value; and flakes basically do what Niv did. And, it's much nicer to just install a flake, rather than having to add channels.

I'm glad to see the first point (flake.nix provides a consistent interface) mentioned. The consistent interface allows for the cli to be much nicer; `nix flake show` can list the outputs.

Re: Why did Nix adopt Flakes?

#58

Am I the only one completely confused by the examples that appear to put command line arguments after shell end-of-line comments? Is that not a typical shell? example: nix run .#cowsay -- flakes are neat Some explanation of what the heck this means would be really useful.

It's nix run, the dot means current directory, # means flake, cowsay is the attribute, and then anything after -- is passed to what's run by that command, which is typical of many Unix programs.

So it's run the cowsay attribute from the flake in the current directory, passing flakes are neat as input to cowsay.

Re: Why did Nix adopt Flakes?

#59
post #46

Earlier quoted context omitted.

I don't fully understand what you are saying, and I don't know what systems you're including in "all". The system you describe building is exactly what nix does, as well as debian, El, and Arch. Their spec files describe both build and runtime dependices, and installing the package does not install things like Make. Nix goes a little bit further by only including runtime dependices that it can find it the build outpu…

RPM rspecs, port Makefiles, Maven, etc. do not just define package dependencies (build, runtime, etc.) and artifacts, they also have to intimately understand how to patch, build, and package the artifacts. Making the build and package system separate from the dependency management separates concerns and allows the ability for a completely declarative “dumb” dependency graph that can be reasoned about without dealing…

> allows the ability for a completely declarative “dumb” dependency graph that can be reasoned about without dealing with build logic that must be executed.

Nixer Domen Kozar called this property 'static metadata' in one of his talks¹ on Python packaging from a Nix perspective years ago.

The thing he was interested in was the ability to evaluate the dependencies of an upstream software package without having to actually 'install' it or evaluate bespoke upstream code to do so. The reason for interest in this within the Nix community is that by default Nix performs builds in a restricted sandbox, and one of its restrictions is that no network access is allowed.

To use upstream build tools (e.g., Maven or Cargo or NPM, etc.) inside the Nix sandbox, then, fetching dependencies and verifying their contents is deferred from the upstream build tool to Nix, which does so in a controlled, deterministic way that just fetches and doesn't have hooks to let those deps run custom code.

In order to make that happen, Nix has to 'know' ahead of time where to fetch those dependencies and what their contents will be, and what you describe wishing for here— a 'dumb dependency graph'— is more or less exactly what Nix wants to consume (although sometimes just a list of pairs of URIs and content hashes will do). For well-behaved upstream package managers, i.e., those which can emit comprehensive static metadata, that's exactly what Nix does: it just translates a Cargo or NPM lock file into its usual conventions for describing source archives, and then that can be used to download those dependencies in the usual safe/restricted way.

For package managers that don't emit adequate 'dumb' package metadata, Nix has to proceed by either emulating and replacing those upstream dependency resolvers (very error-prone) or by a hack implemented as a Maven plugin or similar that inspects dependencies as Maven resolves them and gets the metadata Nix needs.

As for flakes, flake inputs are certainly a kind of dependency that's distinct from package dependencies in the Nix world, and also 'dumber' in the sense that flakes don't have to be 'built' like packages to be consumed by other flakes. And yeah, in the case of flakes that provide packages, you can definitely swap one flake for another and allow that new flake to provide customized build instructions if those are needed for that version of the package it provides. But there are complexities and entanglements that flakes don't/can't eliminate, since downstream dependencies can still have implicit expectations of build outputs, and you can't really know in advance if the package in the new flake will meet all of those. You kinda still have to be able to peek into those and examine them and fix them up in a pinch. Plus you can write a flake in a way that depends on the build process of a package in a flake it consumes, e.g. by using package overrides on something provided in the upstream flake.

--

1: https://youtu.be/ADSM4vR2EQ0

Re: Why did Nix adopt Flakes?

#60

Am I the only one completely confused by the examples that appear to put command line arguments after shell end-of-line comments? Is that not a typical shell? example: nix run .#cowsay -- flakes are neat Some explanation of what the heck this means would be really useful.

The comment syntax for most (virtually all?) shells actually doesn't start with a pound sign but with the word boundary or whitespace preceding the pound sign. You can have unescaped pound signs within tokens in shell languages, and thus they are used (perhaps unfortunately) as delimiters in the current flake URI schema.
Post reply on HN