But it was brutal that I had to just stumble across this. I think the article correctly identifies that there is decent enough documentation in Nix for:
- Beginners to the nix language/concept (Nix Pills)
- Beginner users of NixOS (the NixOS manual)
- Beginners to packaging for Nix (wiki articles, blogs)
But there is a huge, huge gap for the user who is trying to cross the chasm and become a true expert in it all— who wants to understand at a deep level things like how overlays and namespaces work, how bootstrapping works and what is the division of responsibilities between nix and nixpkgs, plus the inner workings of things like buildEnv and stdenv.
[1] - https://www.youtube.com/playlist?list=PLRGI9KQ3_HP_OFRG6R-p4...
I do thank you for the pointer, and I think I've come across these videos before, _but_ to me, video is probably the last format I can assimilate this type of information. Usually, in my experience, well designed systems have a way of making sense so that documentation and understanding flows naturally from base abstractions, and this is something I miss in nix. I would like to try guix to see whether that makes more sense to me, but I am hesitant given that nix seems to have so much more of the mindshare.
One day I'll try to give the video tutorials a chance, maybe it will clear things up. Thanks again and thanks to mr Libbey as well.
Honestly, thats the main revelation I had when going through that playlist. Basically Nix is just attribute sets (which is sort of just a JSON object). The entire thing. Nix files are just some preamble and then they return an attribute set at the end. Understanding that will get you 90% of the way there in terms of understanding the syntax and being able to cut through the "weirdness".
At that point its about understanding actual concepts like overlays, derivations, etc but its much easier now that you understand the attrset concept.
I do realize it's a work of passion done by numerous volunteers, to whom I feel gratitude, but at this point, why can't this be adequately defined, in a written form, in a way that is understandable? To me, the concept of a series of projections of declarative configuration statements onto a final state is not hard to understand in itself; yet, I am somewhat struggling to create and maintain such a configuration without feeling that I am just copypasting bits and pieces from random people.
I guess I just have to bite the apple and spend a few days watching YouTube to see if I reach enlightenment - at this point, I barely understand the function names.
It seems like the community is just a bunch of people who have had that lightbulb go on already, so its hard to go back and view things without the lightbulb on.
Though I say this while continuing to slog through said pain as I find time because once I've learned a particular thing it's always felt like it was worth the effort to get there.
1: Best resource I’ve found is this: https://teu5us.github.io/nix-lib.html
2: The status of lang2nix: https://discourse.nixos.org/t/status-of-lang2nix-approaches/...
(This will just tell you it's imported from lists. `nix edit nixpkgs#lib.lists.sort` will get you the actual definition.)
That means, it can't be just modified by anyone on a whim, all of changes need to be done through proper RFC mechanism. And anything in it must be documented.
Having all that done would greatly improve learning time, it would probably make it easier to maintain other packages as well.
It made sense that it was done this way originally, because initially no one knows what would be needed, but right now many things are solidified and don't change that much.
I found my understanding of the Nix language became a lot better once I started learning some Haskell. Specifically once I understood what currying was about.
My real gripe with Nix is the lack of a complete, easy to find, documentation of its "standard library". Nix Pills & a few wiki pages are far from enough.
How hard have you tried? It's literally two clicks and one scroll away from the official home page: https://nixos.org/ -> click "Learn" -> Scroll down -> click "Full Nix Manual":
https://nixos.org/manual/nix/stable/expressions/builtins.htm...
After months of "It's obviously this" and "you're not even trying" and "have you even looked?" and "there are plenty of examples out there already" and "you should start out by reading the introduction docs" and "you obviously don't know how functional languages work", I just stopped bothering.
I was trying to figure out how to install new machines from a central build host. Neither the straightforward install CD process, nor system.build.qcow2 made sense. I popped into the IRC channel to ask, and it turns out a 'nix build' 'nix copy', 'nix-env --store --set' and 'switch-to-configuration boot' did the trick. That's an extreme amount of power and simplicity that just kind of obviates a whole set of heavyweight processes (eg Debian automated-install). But if you are searching around for the usual type of automated install process, you just come up empty handed looking for it.
I'm still a long ways from understanding everything Nix/NixOS completely, but I've never gotten these kinds of comments apart from the extremely reasonable "you should start out by reading the introduction docs" - that the directions lead with.
And if you have a problem with that, I can see how you might have provoked that kind of response that seems so out of character to me.
I ask questions when I have them, and sometimes I get answers from them, and sometimes I answer them myself.
But I started off reading as much of the docs as I could tolerate before and while getting started, and always trying to self-help before asking for help.
I actually tried to help for awhile, and even started a help guide https://github.com/kstenerud/nixos-beginners-handbook/
But eventually one gets ground down and demoralized enough to just give up. It's a real shame, because I LOVE what NixOS is trying to accomplish.
In your first post in this thread, "high tier" NixOS users were called condescending sadists. This is a libel as far as I can tell based on my own experience.
Then was a list of disliked phrases, and second to last in that list was the instruction to read the manual. I believe in reading manuals, as difficult and time-consuming as the effort may be. This made me think expectations for using the project were wrong.
Now you're linking to a repo you made to attempt to give new users a guide to getting started.
You clearly made an effort to be part of the solution. This is admirable.
I'm trying to connect dots here - what I think happened was, in the course of trying to get help filling in the blanks, you probably exhausted the patience of others trying to help you.
I question if what you've been trying to do works at this point in the project's lifecycle. What you're trying to do is hard enough in a completely mature project. In an environment where we acknowledge the incompleteness of documentation, new command line APIs that are evolving, and new ways of doing things (I'm currently thinking of containers after looking at your guide, and flakes as well), communicating a true North is extremely difficult especially if you aren't one of the core developers immersed in the current state of change.
I don't think the project is mature enough to declare a "right way" to do all the things. I don't think we have enough mature users to support filling in all the blanks, yet, either.
I'm sorry you've had the experience you've had. Maybe after taking a break, you can resume your efforts, but with tempered expectations. We're all asking a lot of people who volunteer their time to build what should be acknowledged as a strategically important approach to computing.
We need more experts. The experts we do have are over-worked and under-appreciated. Perhaps you can help us there one day too.
It's understood and well communicated that the project is not mature enough to be an easy experience for a new user, and that's perfectly fair. But unfortunately, there's a degree of gatekeeperism going on in this community that is making the environment toxic for newcomers.
I've only seen it a few times before, but in every case, the longtimers seem unable to see it, and dismiss complaints by newcomers out of hand. Of course it's to be expected that a certain cohort of newcomers will be toxic and entitled, in which case one would absolutely be justified in dismissing them.
But that is not the case here, especially judging from the sheer number of upvotes my comments on this matter have received, and the number of blog posts in the wild about this very topic.
This is not a problem of maturity, but one of culture. And this is what exhausted me and made me give up on my attempt to make things better.
I hope my original comment doesn't read that way. I mean more "the Nix language isn't much different from something you're familiar with".
> "you should start out by reading the introduction docs"
This one I kinda buy, though.
With programming, with many things, you can get quite far without having to understand all the details. And many tools do quite well by being intuitive to use.
Nix is quite weird. And can be quite difficult. And it's got a small community, so it's under-documented and you won't always be able to find someone who's run into the same problem with a good explanation as to how to fix it.
But I would put up with a lot, if the payoff is more knowledge.
You may not like the reply, but the fact remains: the comment I replied to was a lie. It says there's hardly anything but Wiki pages and Nix Pills and that there's no "easy to find, documentation of its "standard library". And the exact document has been two clicks away from them for a long time.
> I just stopped bothering.
Another problem is your impatience and inability to perform searching and research for necessary information without anyone's help. The lack of focus and motivation to spend a little extra time to discover, learn, and build an intuition around a new toolchain is on you. How much time have you spent on useless media content on youtube or netflix lately instead having another try with the tool?
A couple of examples I've run into:
https://github.com/NixOS/nix/issues/2259 showed people trying to make use of the "hello world" package which was given in the NixPkgs manual, but couldn't quite figure out how to get it to build.
e.g. if you want a package that's a simple script, "writeScriptBin" seems like what you'd want. -- But it's really not clear how to use it from the manual; you'd have to read the nixpkgs source. https://nixos.org/manual/nixpkgs/stable/#trivial-builder-wri...
Is it too much to ask from developers in 2022? At source, the function is well documented and is provided with an example [1]. The only missing part is a rendered HTML with the same information.
[1] https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-supp...
On the other hand, I think it's fair to say NixOS will sometimes require a high level of involvement from its users. When something goes wrong on another OS, it's easy to search for the answer. With NixOS, you have to understand both the Linux part, and the NixOS part.
In 2022 it's not too much to ask from the developers of the tools to provide:
- consistent and up-to-date documentation (that's built and updated together with the source code)
- consistent, readable and understandable error messages
It's not too much to ask for non-production ready software. If nixos is supposed to be production ready, then yes.
[1] - https://www.youtube.com/playlist?list=PLRGI9KQ3_HP_OFRG6R-p4...
As an example, in the video "Packaging a Gem as a Nix derivation", he basically just and copies and pastes another default.nix, changes some strings and mentions he doesn't understand what 'passthrough.updateScript' does, but just changes a string there too.
This doesn't really help me understand Nix.
If you are coming from the perspective of non-NixOS (e.g. HomeManager or just nixpkgs) then maybe start at his rundown of what NixOS is vs HomeManager [1].
Or if you really just want to understand the nix language itself then probably start at 'Demystifying nixpkgs' [2].
[1] - https://www.youtube.com/watch?v=IUsQt4NRCnc&list=PLRGI9KQ3_H...
[2] - https://www.youtube.com/watch?v=oWJaTb5uoT0&list=PLRGI9KQ3_H...
In NixOS/nix, you are essentially extending the nixpkgs source code with your own configuration to build a system, which requires good familiarity with the source. This would be like having to write C code to install packages on another OS. It's a questionable design choice but it does offer a lot of power.
I've programmed professionally in Lisp (SBCL) and Clojure, and done a lot of hobby work in Haskell and Rust. I found Nix the language utterly incomprehensible largely because of documentation and tooling reasons.
Do you by chance know whether a non-Turing complete language like Dhall would be enough to “replace” nix?
Realistically, I'd say Dhall should be viewed as a complimentary typed DSL for Nix instead "a replacement". Dhall shines when it's used as a code-generator for recursive Nix expressions from typed configs that capture the intent of a build pipeline. You can see how it can be generated from this Haskell example, for instance [1]. The [2] shows you the available constructs, that do support recursive calls and recursive Nix sets.
[1] https://hackage.haskell.org/package/dhall-nix-1.1.23/docs/Dh...
[2] https://hackage.haskell.org/package/hnix-0.14.0.2/docs/Nix-E...
Also some of the higher level constructs really aren't clear (like overrideDerivation/overrideAttrs/override, I still don't fully get). And mkDefault/mkForce/etc could be a bit more front and center rather than in "lib".
Also every time I run nixos-rebuild and it takes several+ seconds to evaluate my Nix expression I've got to wonder how much the implementation being this cute functional fixpoint is holding performance back.
Packages are implemented as functions that take dependencies as arguments, do some stuff and ultimately output the result of calling mkDerivation (i.e. a derivation).
`override` allows you to change the arguments of the package, while `overrideAttrs` allows you to change the arguments of mkDerivation: the implementation of the package itself. `overrideDerivation` is essentially a deprecated `overrideAttrs` version.
https://nixos.org/manual/nixpkgs/stable/#chap-overrides for a better explenation.
`overrideAttrs` changes the arguments of the former, while `overrideDerivation` changes the arguments of the latter. The reason is it's "deprecated" is that it forces a full evaluation of `stdenv.mkDerivation` before it can continue and it override the lower-level derivation, so some niceties that Nixpkgs provides don't work with it.
Except that they concoct weird custom terminology for everything.
It's not a hashmap, or a map, or an object. No. It's an attrset. Riiiiight.
It's not a build script, it's a derivation.
Etc, etc.
This was intentional. Most hashing algorithms don't guarantee a stable ordering of keys. Nix was inspired by a research project called Aterm, which did have this property. Also, you can do things like reference other keys in an attr set, which many other dictionary data structures don't support.
> It's not a build script, it's a derivation.
Derivation encapsulates everything which goes into a building something. Dependencies, env vars, flags, sources, patches, the build script, package version, and package name all get packed into a derivation. These paramaters get hashed which is how the hash for the store path gets determined.
Derivations can be thought of an unambiguous build "recipe", which has already resolved based upon all configurable inputs (dependencies, build platform, host platform, target platform) .
https://book.divnix.com/ch04-01-create-a-derivation.html#ins...
Nix is optimized for creating reproducible builds.
> This was intentional. Most hashing algorithms don't guarantee a stable ordering of keys.
Then it's an ordered map.
Since you're creating a new language, you can say right up front "in Nix, all maps are ordered maps" and then just refer to them as maps.
There is existing terminology for all of this stuff, and it should have been reused.
Yes, because derivation's aren't build scripts. If you look in a .drv file (or better yet, pipe it through pretty-derivation), you'll see that derivations have a reference to a builder (i.e. the path to a binary), but derivations themselves aren't build scripts; they define the arguments and env vars for the builder (plus references to dependencies, output paths, and OS/architecture).
In practice, pretty much everything in Nixpkgs uses Bash as its builder; and almost all of those use the same 'default-builder.sh' script. However, Nix itself is independent of Nixpkgs, and we can give it any executable we like.
I think this one's a fair example of a specific terminology, though? The idea of building a package in a certain way, and storing it in a certain way, is foundational to the Nix packaging system.
Like "elaborated build script". Or "transitively-hashed build script".
In particular it's not an "elaborate build script. The actual derivation is basically just a json file¹ with a path-name that's a function of its contents that includes specifying everything that goes into the build (env-var settings and arguments, the input sources, other required derivations, the build script, the standard environment -- all with transitively hashed paths) as well as what comes out of it.
They could maybe have called it build-spec, or something like that, but I think giving a novel thing a novel name is in fact novel is less confusing than trying to repurpose some existing terminology and trick people into thinking it's something they are already familiar with when actually it isn't.
¹ It's not actually json, but that's just some historical accident; `nix show-derivation ...` will actually output the derivation as pretty-printed json. But the key thing is that it's just simple data, not an executable script.
The former means "with all the details spelled out explicitly". The latter means "intricate".
And, I've yet to see a .drv file that contains absolutely 0% shell script. Let's be honest, nix is used mainly as a metaprogramming language for bash.
Because let’s be honest, types are user documentation as well, and the project would benefit greatly from the latter.
Seriously though, javascript is not a great language if you are looking for robust determinism. I can understand their decision to go elsewhere, given the domain and design.
But yeah I agree. The thing is, if all you need is robust determinism why do you need a full functional language with currying and other complex concepts?
Google had the same problem for Bazel, and their solution (Starlark) is way easier to understand.
Yeah, that's a good point.
I don't see any reason determinism requires a functional paradigm. That said, the functional language communities probably value determinism more than the others, currently.
Choosing a language whose community values align with your needs can be a good thing.
It's too simple and straightforward. Writing Nix expressions is a bit like writing Javascript without frameworks or libraries.
Some sort of opinionated framework that compiles to Nix would be great for maintaining large Nix projects. (The Javascript world already went though this phase.)
I don't agree with this direction, though. Basic packages can already be described pretty simply using native nixlang, and the complexity scales well— you can add patches, fixups, flags on dependencies, extra fetcher args, whatever and it's a pretty smooth ramp all the way up. Whereas it would be considerably more jarring if you could use the "simple" thing up until the point where you abruptly hit a wall and then suddenly had to start over in real Nix when you hit that one thing that happens to require it.
Quite apart from that side of things, if a significant portion of nixpkgs were converted to the new simplified package definition style, it would majorly shrink the potential pool of example package definitions for novices to examine.
No, I'm talking about things like classes, abstract data types, modules, type checking and docstrings.
"Programming in the large".
Nixpkgs and NixOS does its own hand-rolled versions of these for each subproject. Eventually (a long time from now in a galaxy far away) we'll have some sort of standard Nix++ language and standard library.
And a proper type system would be awesome.
Regarding docs, it is interesting that portions of the nixpkgs source do seem to have docblock-like comments above the functions, but AFAICT there's no formalized process for extracting or rendering those. Given that https://github.com/nix-community/rnix-parser exists, I wonder how big of a leap it would be to actually extract those, render them into rST pages, and generate a searchable Sphinx manual.
Out of curiosity, are you talking about Typescript? Not really a framework, but I can't really think of a framework that 'won' in this sense for JS, and also compiles to JS.
On the front-end there's Svelte, which is actually compiled with Javascript, and React, which is has the biggest market share of opinionated Javascript frameworks, but at best you could say JSX is compiled to HTML.
On the back-end, there's express, but that doesn't involve any compilation, and is far from opinionated...
But also things like Vue do their own compiling step too.
I agree that language is too simple. Also I think some degree of IDE / language server support would help a lot. Refactoring modules, writing and importing custom functions was a bad experience for me - some arcane stacktraces were common, using repl was too verbose and with no clear way to debug whole configuration.
Maybe this is nitpicking, but: the Nix language is about as straightforward as "JSON plus functions". Maybe that is difficult for people who haven't had an experience with pure/functional programming?
Though, yes, the way Nix is used can be quite complicated/sophisticated. -- Even if all of Nixpkgs were translated to JavaScript, I think it'd still be complicated to understand. (Though I suspect using a more general purpose language would allow for more footguns).
+1 to the sentiment that most of the time you can get by just fine, but when you can't, NixOS is more difficult to make progress with compared to other Linux distributions.