108 comments

[ 4.5 ms ] story [ 166 ms ] thread
I switched my personal dotfiles to nix recently, and the “poor documentation “ comment here really hits home.

Trying to learn /how to use/ nix was awful. I found lots of guides, almost always incomplete, and oftentimes directly contradicting each other. It took me weeks to get a working build and much of that time was anything but fun.

I like the outcome, and I’m glad I took the time now, but it was a slog that I don’t think I could really recommend to any of my peers.

It’s too bad guix went full hardcore FOSS and refuses to support macs, because they seem to have better docs and using a language that I can use outside of my package manager makes a lot more sense to me.

I keep reading, this, and keeping being told this. Yet I switched every system over to nix and have found no thing but the best examples documentation and help from nix to do so.

Within the span of a afternoon and a bit a reading I went from zero, to a script that lets me setup an entire dev systems with just a few commands in a vm, and or even on hardware.

If anything the Nix documentation is just as good as every other thing out there. What is different is there are more than one way to do many things in Nix. This to me I think is the core of complaints. Its a language, and thus the language has may expressions that result in the same outcome.

The second bit I think people struggle with is it is functional. If you look at Nix complaints they appear to nearly be identical to that of Haskell.

I also didn't notice that the documentation was especially bad. I'm thinking maybe it makes more sense for some programmers?
Then you are a superhuman. I too went through weeks of pain and suffering to get my nixos hypervisor running, and if I were to lose my script and have to start from scratch again, I'd just install Debian instead.

I would never recommend nixos to anyone. The concept is awesome, but the execution is terrible.

What I often find is this “ought to know” treshold. Parent comment user is probably familiar with lingo you are not. Documentation often assumes a certain level and a writer does not imagine a less capable user.
Yes, the Nix community has great reference docs for people who already know how things work, for most things imo. At the same time, it isn't always obvious enough where to find a good introduction to terms and concepts used. But materials of that kind are increasingly available and general gaps are being filled with a lot of focus lately.
By documentation, I believe people mean tutorials. At least, lack of tutorials is my complaint. I've read all introductory material. I want to build a customized version of emacs on nix, yet I have no idea how to do it or where to start.
Why use a tutorial when ChatGPT has you covered?

> How do I create a nix package that clones eMacs from GitHub and builds it from source?

{ pkgs ? import <nixpkgs> {}, fetchFromGitHub }:

let

  emacsSrc = fetchFromGitHub {

    owner = "emacs-mirror";

    repo = "emacs";

    rev = "master";

    sha256 = "0xabcd1234";

  };
in pkgs.stdenv.mkDerivation {

  name = "emacs";

  version = "27.1";

  src = emacsSrc;

  buildInputs = [ pkgs.autoconf pkgs.make ];

  configurePhase = ''

    autoconf

    ./configure --prefix=$out

  '';

  buildPhase = "make";

  installPhase = "make install";

}
As usual for ChatGPT this is full of mistakes and bad code. The buildPhase and installPhase it writes are completely unnecessary and worse than the default, the configurePhase might work in some cases but most likely won't, and it's unnecessary when instead autoreconfHook should be used, stdenv/autoconf should be taken as an argument for the function returning the derivation, autoconf should be a nativeBuildInput, make is already in stdenv, etc.
You're also supposed to call the pre and post hooks for these phases.
More fundamentally, even if the code produced by ChatGPT worked and was high-quality, why should a new user have to rely on a chatbot instead of useful/up-to-date tutorials and guides?
> sha256 = "0xabcd1234";

Am I right in assuming this is a ChatGPT misunderstanding, or is it a wildcard SHA256 in nix to allow any download?

Definitely not a wildcard, such things are not allowed. You can fetch at evaluation time with the built-in fetchers (builtins.fetchgit, builtins.fetchTarball, etc) and not provide a hash, which makes the expression "impure", which means the expression wouldn't be acceptable in nixpkgs and it has consequences for flakes.
> It's a language, and thus the language has may expressions that result in the same outcome.

First it's a distribution and a package manager, and the guidance regarding these is sub-par. Especially with what there is of documentation being split between the old and new UIs, then being told about flakes but that they're experimental so it's not clear whether you should or should not use them.

I just went to the nix website, clicked "first steps with nix" and I get https://nixos.org/guides/ad-hoc-developer-environments.html

Is that useful? I'm sure to somebody who already knows what they want out of nix it is, but the first thing I'm told is that shell environments exist and are useful to "use the tool without having to install the software.". Ok, but what if I want to install the software? Then there's listing of what's essentially a magical invocation out of nowhere:

    $ nix-shell -p 'python38.withPackages (packages: [ packages.django ])'
I can understand that (or at least reach what I assume is an understanding), but there's no real explanation to give me knowledge to expand upon, if anything the explanations are worse than useless:

> We create an ad hoc environment with $PYTHONPATH set and python available, along with the django package.

thank you very much, that confirms I'd about interpreted the line correctly, but you've not told me what `withPackages` is or where `packages.django` comes out of so I'm not really helped.

And apparently the next step is "declarative and reproducible developer environments", or possibly "towards reproducibility: pinning Nixpkgs"? Or even better, "To quickly setup a Nix project read through Getting started Nix template", I have no clue what a nix project is or why I'd want one.

There's not just a step missing here, there's an entire floor, possibly building. It's like the nix community saw how git is taught and went "we can do worse".

(comment deleted)
> Is that useful? I'm sure to somebody who already knows what they want out of nix it is, but the first thing I'm told is that shell environments exist and are useful to "use the tool without having to install the software.". Ok, but what if I want to install the software?

Why would you go to https://nixos.org/learn.html, click on an introductory example titled "Ad-hoc developer environments" and complain that it doesn't explain how to permanently install software?

> but there's no real explanation to give me knowledge to expand upon

Again, you're pointing to a page containing TLDR examples. That's not the right place for an in-depth explanation.

> There's not just a step missing here, there's an entire floor, possibly building. It's like the nix community saw how git is taught and went "we can do worse".

No surprise because you missed the entire manual.

> Why would you go to https://nixos.org/learn.html, click on an introductory example titled "Ad-hoc developer environments" and complain that it doesn't explain how to permanently install software?

Because it's also the one labelled "First Steps with Nix". As in, the big orange button which immediately follows "Install Nix", and the second thing the Nix community apparently wants me to do to learn nix.

I literally did three things: I opened the nix website, I clicked "learn" (it's also what you get when you click "getting started" from the front page by the way), assumed I'd installed nix (I did check if there was seemingly critical information there, there isn't) then I clicked the following step.

I'm not quite sure what you'd want me to do.

> Again, you're pointing to a page containing TLDR examples. That's not the right place for an in-depth explanation.

I'm not asking for an in-depth explanation, I'm asking for pointers to the surface basics. The page tells me that "we’ll cover that in later tutorials" but I've no idea where those are, and none of the 5 links listed in the "next steps" seems helpful in any way. The least unpromising one ("Nix language basics") certainly didn't tell me anything about python.withPackages.

And again it's not "a page containing TLDR examples", it's what the website told me to start with.

> No surprise because you missed the entire manual.

The manuals which are at the bottom of the page (so one would assume the things to check after the one at the top of the page)?

And which are if anything even worse? The first one ("Nix Manual") goes directly from "you can upgrade packages" and "nix lets you rollback profiles" to "the nix language" to "advanced topics: remote builds".

I still have no answer to any of my question, but now I know that I can configure how many cores Nix will use when it builds derivations.

I still don't know what a nix project is or why I would want one, why I would want a derivation, though the manual does tell me they're important (why?)

I still don't get why "first steps with Nix" has to include installing packages permanently. Making persistent changes is exactly the kind of thing that is better avoided before users have had the chance to learn anything.

> And again it's not "a page containing TLDR examples", it's what the website told me to start with.

So the website recommended you to read a page containing introductory examples. Not sure why you insist otherwise.

> And which are if anything even worse? The first one ("Nix Manual") goes directly from "you can upgrade packages" and "nix lets you rollback profiles" to "the nix language" to "advanced topics: remote builds".

What? The there are far more chapters in the Nix manual than just the three you mentioned.

> I still don't get why "first steps with Nix" has to include installing packages permanently.

Because if I don't know nix (which, you know, would be why I'd be reading introductory material) I'd be looking to use it, and my basis would be to do would be the way every other distro works.

And if I have to type `nix-shell -p python38` every time I want to run Python and `nix-shell -p vimMinimal` every time I want to edit a file, the experiment is not going to last long.

> So the website recommended you to read a page containing introductory examples. Not sure why you insist otherwise.

I'm not "insisting otherwise", I'm observing that it's confusing, utterly useless, and provides no real guidance towards improvement. And it's where the site told me to go as my second step into nix.

But apparently you're perfectly happy that this is what the "first steps with nix" should be (after having berated me for going there), so... proving the point I guess.

> What? The there are far more chapters in the Nix manual than just the three you mentioned.

Have you actually looked at them? ever?

1 is a quick overview of the entire thing, none of it actually helpful.

2 is a few basic commands expanded upon in (4)

3 is a lot of time spent on installation details

4 is where the meat starts, "You can upgrade package" is 4.1, "profiles are a thing" is 4.2, 4.3 is "nix will eat your disk space" (useless to a beginner), 4.4 is "channels" (even worse), 4.5 is "sharing packages between machines" which could not be less useful at this point./

5 is, as I said, "the nix language" covering the basics, with 5.4 mentioning derivations and going into plenty of details, none of them actually useful or telling a beginner why they should care

Following which we reach 6.1 "remote builds.

From a beginner's perspective, tits on a bull are at least funny, the nix manual doesn't even have that going for it.

Have a nice day, I'm done wasting time on you.

First of all ...

> after having berated me

Wow, I must be a terrible person, except I never recall berating you. I double checked, and it's just me expressing my disagreement. I'm not the one saying things like "It's like the nix community saw how git is taught and went 'we can do worse'" or "I'm done wasting time on you."

> Because if I don't know nix (which, you know, would be why I'd be reading introductory material) I'd be looking to use it, and my basis would be to do would be the way every other distro works.

Nix isn't a drop-in replacement of apt or yum. It's possible to use it like one, but that would be missing the whole point. Most of the benefits of Nix is obtained by writing configuration files tailored for each project you're working on. That's another reason why the examples don't start off with a replacement of "sudo apt install". Creating localized development environments is one of the primary use cases of Nix.

> Have you actually looked at them? ever?

Of course I did. I read the entire manual when I learned Nix. That's why I get the impression that your summary of the Nix manual makes it look more distorted than it actually is.

For example:

> 1 is a quick overview of the entire thing, none of it actually helpful.

The said overview includes instructions for installing packages permanently. You clearly stated that is what you were most interested in, so it actually should've been helpful for you.

> First it's a distribution and a package manager

Nope, it's a language, and thinking of it as those things, even more so firstly is probably part of the struggle.

It's a language that you use to get your computer to do specific things. In this case, it might be a "package manager" and in the other case it could be a "distribution".

When you write go or rust to print "hello world" to the terminal you don't go around and call these things "printers", or "hello worlders".

It's a language, just like rust, go, php, bash, ed, awk, and brainfuck. Your first example even shows you using the language why proclaiming ahah! shell thing, or package manger! -> `'python38.withPackages (packages: [ packages.django ])'` is using this language to instruct the computer to do something. If you don't want to take the time to learn the language and understand its outputs, and want to just think "this is a package manager" then you are going to get lost.

> When you write go or rust to print "hello world" to the terminal you don't go around and call these things "printers", or "hello worlders".

That is the exact reverse of the relationship between Nix and Nix.

When I write in Go or Rust, a printer is a tool I might use to achieve a specific sub-part of my over-arching goal.

My goal is not writing nix programs, I've got better programming languages available for that. Nor are the nix OS or package managers utilities of nix. The relationship is the opposite: the nix language is a tool provided to manage software or distribution in order to actually do things.

> Your first example even shows you using the language why proclaiming ahah! shell thing, or package manger!

Aha yes, that well known language of whatever apt is, checkmate!

> If you don't want to take the time to learn the language

I don't even mind that, I'm pointing out that the official nix documentation I got from the official nix site following its own recommendation gave me something utterly unhelpful which neither helps me in furtherance of my goals, nor provide any obvious steps towards that.

Having learned that `python38.withPackages` is a function called with an other function `packages: [packages.django]` as parameter does not help me either.

> want to just think "this is a package manager" then you are going to get lost.

I guess I should remove nix then, since it's not a package manager and that's what I'm looking for?

You should maybe think of fixing the branding by the way, because some folks slander nix by calling it an OS, and there's pages talking about "nix: the package manager".

In fact that's literally the tagline of the primary manual:

> Nix Manual: Nix is a package manager which comes in a form of many command line tools.

> Introduction: Nix is a purely functional package manager.

> My goal is not writing nix programs

That is your issue. This is a language to write "operating systems" and "packages" it is not really a "package manager".

You use different programs and libraries to work with different systems.

>I guess I should remove nix then, since it's not a package manager and that's what I'm looking for?

Yes, I think that is the flaw, it's a language, that lets you write code that produces an output.

Nix actually has far better than average documentation compared to other typical open source projects. I started using Nix years ago on Ubuntu to quickly install a package that wasn't present in Ubuntu's repository. Eventually, I began customizing packages using Nix expressions. Before I knew it, I migrated my existing systems over to NixOS. What I can say is it wasn't at all the uphill struggle that's associated with Nix in online discussions. Even though the documentation isn't perfect and going through active improvements, there's a considerable gap between Nix's reputation regarding documentation and my own actual experience.

What surprises me is that people tout RPM/Chef as easier replacements to Nix/NixOS. The assumption about those being "replacements" of each other is questionable because they address different needs. What's even more questionable is the part about RPM or Chef being easy. I have dealt with those two for years as part of my day job, and they're both far from easy. I still have troubles with them to this day. Documentation is far more lacking than Nix, and it's not because things are obvious. If you encounter any trouble, you almost always have to dive into the source code. Navigating the source code of RPM or Chef is a nightmare because the code is scattered across countless different repositories and it's impossible to guess where to look for to begin with. Choice of programming languages doen't help here too. Chef is written in Ruby, which has a tendency of making code ungreppable due to its metaprogramming features. RPM has its own macro syntax which works similar to the C preprocessor. It's very terse and full of gotchas. Navigating around Nix code is much, much easier in comparison. Everything you need is in a single repo, https://github.com/NixOS/nixpkgs, and written in a JSON-like language.

Many people also claim that Nix is hard because it requires a functional programming background. That too doesn't match my experience. Nix expressions are basically JSON with functions. Learning the syntax is a non-issue if you know JSON and some common programming language constructs like conditionals, functions, map, filter and reduce. The only functional programming exposure I had prior to Nix was LISP, in a university classroom. Yet I didn't experience problems learning the syntax. The hard part is learning how to actually utilize the language. The documentation and some grepping around of the Nixpkgs codebase helped a lot with this.

My complaint is chiefly about practical implementation. “I want to use nix as a package manager across systems” is far too difficult for a new user.

One document tells you to flakes, another tells you that it’s experimental and should be avoided.

One document tells you that you should use Darwin modules and home manager, and then completely omits the fact that the linked home manager scripts don’t work with Darwin by design leading to “why the fuck isn’t this file they tell me should be auto generated not being created”.

Because the official docs don’t seem to cover real world use cases, you end up relying on a labyrinth of out of date and conflicting user contributed tutorials and it is very frustrating.

Once you know what to do nix is simple enough, but learning what to do is outright painful; if you don’t believe me look to the other replies to my comment.

I agree with the Guix bit. At some point, I tried using Guix System on my laptop (with wireless support), and of course I was greeted with « use a wifi card that respect your freedom » or something of the sort.

At some point, I might try again, using NonGuix ( https://gitlab.com/nonguix/nonguix ), but right now I'm not using Guix SD. Instead, I try to use Guix on small projects (like building websites using pelican), without going full Guix.

What I'm most impressed with Guix is the time machine and Software Heritage integration, but it still needs a lot of improvement for developers, for example allowing to specify environment variables in manifest.scm files.

> for example allowing to specify environment variables in manifest.scm files.

There is already .envrc or .dir-locals.el? And manifest is just - well - manifest. By definition it has to be 'plain'. I mean, there are already a million ways to load env vars so why'd you want guix to do that too and from manifest.scm of all places?

Because instead of distributing two files (channels.scm and manifest.scm, or flake.lock and flake.nix), you have to execute monstruosities like `guix shell --container -m ./manifest.scm -- bash -c 'GUIX_LOCPATH=$GUIX_ENVIRONMENT/lib/locale LC_ALL=fr_FR.utf-8 exec jekyll build'`, which is how I build some websites I have.

To me, that's not ok from an user experience point of view.

Exactly my point. You can already do it with direnv, have guix shell once you cd into dir and then just do `jekyll build`.
Does

  nix develop -c jekyll build
not do the job for you? (For a single development command—for deploy 'nix build' should be set up to do the right thing, including setting LC_ALL if necessary; and to enter a dev shell just 'nix develop' should work. Nixpkgs installs glibc with a full complement of locales by default, which has its downsides size-wise but should prevent any troubles when setting LC_ALL=fr_FR.)

Or, for an automatic setup,

  cat > .envrc
  use flake
  ^D
or, for an automatic setup with caching[1],

  cat > .envrc
  if ! has nix_direnv_version || ! nix_direnv_version 2.2.0; then
    source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.0/direnvrc" "sha256-5EwyKnkJNQeXrRkYbwwRBcXbibosCJqyIUuz9Xq+LRc="
  fi
  use flake
  ^D
(I don't have nix-direnv installed systemwide because it ignores the --no-write-lock-file flag I need to pass sometimes. If you put some of your config in default.nix or shell.nix or whatever, you’ll need to watch_file resp. nix_direnv_watch_file those.)

[1] https://github.com/nix-community/nix-direnv#direnv-source_ur...

Oh, in Nix, this works flawlessly, I was talking about Guix in the comment !
Use `setenv` inside the manifest.

    (setenv "MAMA" "MIA")
    (specifications->manifest (list "hello"))
Nonguix is new to me. I may give it a look at some point but I’m already over the pain threshold on nix.

Any idea if nonguix will allow an install on macOS? I really want a system like this that I can use on my work MacBook and remote Linux servers.

A caveat with nonguix: there aren't any binary repos, so you have to compile Firefox from the scratch.
This hasn't been true for about a year. Nonguix has a substitution server that includes Firefox and the Linux kernel.
> for example allowing to specify environment variables in manifest.scm files.

Just use setenv in the manifest:

(setenv "MAMA" "MIA") (specifications->manifest (list "hello"))

Then `guix shell -m this-file.scm` enters a shell session where "hello" exists and the env var MAMA is set to "MIA".

This sadly also sums up my short-lived stay with NixOS. Tried on multiple occasions to get a working system to no avail and ultimately made me go back to Fedora where I remain until this day.
It’s typical of certain areas in tech (like here) to not document, to not care about up to date information, and only as a last resort. You need people who can manage that and create a culture of documenting.
I have been starting to suspect that a big part of the gap may be a sort of field guide to real-world patterns with context on what's new/old, where they are used/useful, and so on.
There's an element of truth to the "poor documentation" complaint, because there are tutorials etc out there that are out of date, incomplete etc. But the official nix project has excellent documentation.

I think the problem is that nix is just hard to learn. It's really different from most package managers, but people expect to look at a few examples and just pick it up intuitively. It's a whole different paradigm, with a custom programming language that also has a different paradigm. (Though Haskell folks eat it right up... no surprise there.)

It's gonna take time and effort to learn it, and there's just no way around it.

> But the official nix project has excellent documentation.

If it does, it's really well hidden. Because the nix manual certainly is not that.

> I think the problem is that nix is just hard to learn.

No, the problem is that nix offers no guidance or real help along that path. You go to https://nixos.org/learn.html and you've got essentially nothing helpful beyond the installation (which is easy enough). And it gets really bad when you get there from https://nixos.org/explore.html with no prior knowledge.

> Though Haskell folks eat it right up... no surprise there.

They're used to having to power through absent documentation?

> It’s too bad guix went full hardcore FOSS and refuses to support macs,

This is either a misunderstanding or misrepresentation of the issue. We don't refuse to support Macs. Consider this:

- the value of Guix is in building up a package graph all the way from the very bottom (a tiny binary seed without parallel in other distros); this uses glibc. - glibc doesn't support Darwin - the only way to build software on a mac is to sign an EULA and use proprietary software (Xcode and the SDK).

It's easier to build software for Windows than for a Mac. If it was about "full hardcore FOSS" (what a weirdly judgmental term!) then we wouldn't support building for WSL or cross-compilation to mingw64, but we do.

Personally, I have no interest in working my ass off to get a subpar implementation of the package graph grafted on top of a huge binary blob (Xcode and the SDK) just to elevate a highly restrictive proprietary platform.

Until Apple commissions this kind of work it is still preferable to just use Guix in a virtualized GNU system.

> … just to elevate a highly restrictive proprietary platform.

This is the attitude I’m referring to when I say “hardcore FOSS”. You can choose to see it as a judgement if you want, but I view it as an implementation detail precluding my use of Guix.

“It’s hard and it’s not worth my time” is totally fine, I don’t expect projects to cater to my needs; but it’s worth calling out that it really seems like your chief complaint is that Apple is not FOSS (aka: proprietary).

I can't build any software for macos without signing a contract and buying their hardware. The fact that it is proprietary is the obstacle here.
I've only used nix at home for 2 months but my biggest pain point is just dealing with testing out random GitHub projects where I need to install dependencies from some language's package manager.

There is usually a nix way, but I don't wanna build a custom nix script every time I want to test something out.

However I found that using distrobox solves this problem for me quite well. It's a way to easily create and enter another distro from the terminal while it inherits everything else from the host.

So whenever I want to try a random python project I just do it there and don't care about making a mess, while my host system is clean.

I'm sure there are better ways to do these things, but I can't seem to find answers that don't seem to involve a lot of work.

> When we use NixOS, and we want to use a package that is not available under NixOS / Nixpkgs (which happens quite often), we have only one choice: pack it into NixOS.

That's not the only way. It's definitely the easiest option, but you can also create a temporary fhs environment https://github.com/ElvishJerricco/nixpkgs/commit/05742c15d5a...

What’s even easier is using steam-run which is technically intended to run games which expect FHS environment on NixOS, but it works excellent to run any binary which was built on another distro
Toward the docs point, nowhere in the Nix manual do they spell out the FHS acronym. It's just the Linux derivation of the standard Unix filesystem structure, something that I never knew had a formal name (Filesystem Hierarchy Standard) or centralized authority.

That kind of re-emphasizes to me that regardless of the value Nix might offer me, I'm not and probably won't ever be the audience for it, because if it assumes I know that well enough to recognize it by acronym then it's going to assume I know a lot more than that. I can look forward to a few months of Googling and tangents just to get a grip on its fundamentals.

You can't describe everything every time, at some point you need to use more concise naming for better communication. While it would be nice to improve things for beginners, this one seems pretty good already. Searching for "nix standard directory layout" brings up relevant blogs along with a Wikipedia page for FHS. Not bad.
To be fair, FHS isn't an acronym introduced by the nix project. It's not that well known though, so I do agree that it would make sense it introduce it.

More generally, it seems that the nix documentation (including the reference docs) suffer from not having been developed systematically to introduce things in dependency order.

My very personal main pain point is documentation: Nix/NixOS do have some, but mostly or too little or deprecated.

Where is a proper Flake documentation? Where is a proper $newNixFeatureInVogueNow?

The second pain point is: Nix might sound nice to read and write as a language for Haskellers, but most people actually aren't haskellers...

The third is essentially the fists, more specified: target. If the target is desktop, or server, or HPC, or development docs should be shaped per target. Actually NixOS is designed mostly with dev desktops and infra target, but docs are not even for new devs, more something added aside just because it's part of the duty provide them in some form...

> Where is a proper Flake documentation?

That one actually exists in the right place. (Assuming you meant the flake file)

https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3...

Let's say a new user start using NixOS: where he/she find a good starting point to quickly deploy hes/shes first flake-based NixOS test desktop? Than the user want a bit more, let's say "hey, since it's damn easy let's build a custom ISO with my testing desktop config for replication. Sure some blog posts do exists, but from official docs? A third point "oh, nice, now I have a reasonably good NixOS config, a way to deploy it from a custom ISO on a local machine. What about a LAN-wide deploy?" (here is the delirium, and ok, not only for NixOS but for most OS out there, NixOS in particular have stared NixOps, but now seems a bit abandoned, Disnix is not really documented and so on).

That's why my third point is separated from the first: what's the target? The above example is what I see as a classic GNU/Linux nerdy/a bit navigated user path to NixOS for a personal usage as a desktop and for a home-lab-alike infra. For such target there is no good docs at all.

For some niche, like HPC for Guix, again there is nothing "targeted". Similarly for all NixOS use cases I can imaging.

That's why I conclude that docs was produced as a separate stuff "we need to have, not nice to made, not really useful" instead of the base to create newcomers paths to NixOS and also drive future design decisions because writing targeted docs in natural language is the best way to spot very high level logical design issues very hard to get up front discussing between devs and quickly produced code.

Counter-anecdata: I took to Nix very easily, including its more Functional aspects, despite my little prior experience with FP and 0 experience with Haskell specifically.
The real pain points are:

1) Abysmal contributor experience

2) Lack of typing in nix language and very limited debugging capabilities

3) Lack of interface concept in nix language

4) Lack of any markings on dependency graph edge

5) (3) and (4) makes impossible to have anything alike to gentoo's slots. Nix might be the only right way of doing slotting but it's effectively incapable of that.

What do you mean in pt 1? I've not experienced any issues there, but curious to hear from others.
Normal flow in other distros I contributed to: "thanks for the patch, we'll do the rest".

Nix flow: your patch is not done according to our guidelines, so fuck off. Still not. Still not. Read the guidelines. Still not, read the guidelines. You have to squash commits manually, we won't enable autosquashing because someone important doesn't like them. Nope, your time isn't valuable because there are too many of you and just one nix.

It's like they enjoy spending time to tell occasional contributors, who can't memorize all nix rituals, "fuck off" instead of spending that time to do the necessary finishing touches.

So, critical issues/vulnerabilities remain unpatched, some formulas are outdated by 5 years, because the relevant maintainer says the old package works for him but new one breaks something on his machine and offers to investigate his issue on your own by a single log line. Of course completely ignoring all _your_ issues which are fixed in an upstream patch made one year ago.

I know people who decided not to make a single contribution to nixpkgs until the things change because of that shitshow and I joined that movement. It's really easier to have a personal private fork of nixpkgs and make all the changes there instead of dealing with the upstream and that's what I would strongly recommend to any nix newcomer.

This couldn’t be any further from my experience. Instead of being told fuck off, I was offered (and later offered when I became a maintainer myself) constructive criticism, often times with the patches, required to make it up to standard, included.

> maintainer says the old package works for him

We’re all just volunteers, who are doing this in our free time. Usually this works well enough for most packages, but you are always free to submit the fix yourself on nixpkgs ;). At least compared to other distros, that workflow simpler.

> can't be any further

Probably you are lucky.

> always free to submit

I did. The problem is that in this particular case there is one guy with merge rights who doesn't want to update a package because it breaks something for him so the package is outdated by years. He provided me an excerpt from his logs and said that the update doesn't work for him. Period. They don't even think that the outdated package doesn't work on _modern_ hardware.

Which package was it?
Not so popular one. Doesn't really matter because the annoyances happen on regular basis.
> Nope, your time isn't valuable because there are too many of you and just one nix.

This ... seems entirely reasonable, though?

As you point out, having to do extra work on behalf of others isn't desirable.

-- If a pull request is made and the maintainer(s) don't like it, the options are "reject it", "maintainer puts in extra work to accept it", "pull request author puts in extra work to get it accepted".

With as many open PRs to nixpkgs as there are, it seems reasonable to ask that pull requests are as streamlined as possible.

That this isn't a great experience for new (or infrequent) contributors is unfortunate; although, "contributing" was raised as a pain point in the last community survey. https://discourse.nixos.org/t/2022-nix-survey-results/18983

> This ... seems entirely reasonable, though?

Yeah. It's better to spend more time repeating "read the guidelines" instead of fixing the commit message. And of course it's better to keep critically vulnerable packages (netatalk, potential remote code execution) for months and piss off the maintainer (not me) instead of turning on the autosquash.

This may be annoying, but it makes sense at scale. If you learn the rules, you'll do it right the next time. If I fix commits, I'll handle a fraction of the PRs I could otherwise - and submitters will learn that anything goes (And I am still fixing the most trivial issues)

For security issues, mentioning cve gives the pr a security tag which helps speed thing up.

I'm not a full-time nixpkgs developer being paid for that. I'm willing to make occasional contributions but won't if it costs me too much. If it's cheaper to maintain a private fork I would do exactly that.
That's the thing though - almost nobody is. Neither are the people merging the PRs, and while there's significantly fewer committers than contributors, the current setup just makes sense at scale. I'm not saying it's a good end result, just the most efficient at the time.
I can say I've had merge requests denied because I used the title "xxx: init @ 1.0.0" instead of "xxx: init at 1.0.0", but when upgrading packages you must use a symbol, either "->" or "→", but initialization doesn't allow a symbol. Nitpicky but fine, I update the commit title and I wait 2 months for approval+merge. There's also a long disconnect between approved vs. merged in general; I currently have 2 or 3 merge requests already approved by community members for over 2 weeks, but no merge. It's very handy to have friends/coworkers that can help you get through a fast approval so the merge wait can begin ASAP, otherwise you'll be lucky to even get that review.

I agree that if the maintainers are compensated for their time, patches would be a lot more efficient in these scenarios to clean up the loose ends.

That's exactly what I'm talking about and I don't see any point in making any contributions there. I just feel better maintaining my own private fork.
I've had to resort to doing the same a lot of the time as I await the merge process. Even after merge, it may take Hydra 3 days to get your changes from the default branch to even nixos-unstable for general usage. I find a fork a bit easier than piling overlays and forgetting to move on from them.

My favorite was when the GNOME ISOs got so bloated it no longer fit on a DVD size-wise and nothing could move to unstable for over a week while folks hem and hawed about what to do with that situation. Not saying a little bikeshedding + solution digging isn't good for the long-term, but it seemed so odd that this was preventing anything from going to unstable. (https://github.com/NixOS/nixpkgs/issues/159612)

The pr naming is strict, because a lot of the ci and automatic processing depends on correctly named commits. And you do want them to run well.
Seems like the naming should be its own CI check (or a comment bot or something) rather than result in rejection by a human.
Contributor experience for nixpkgs has been better than my typical experience with other projects, once I learned the flow.

Scale of the repo and massive numbero of new PRs makes it easy for PRs to get lost and not reviewed, if you're having trouble with that you want to ask for help either on the PRs awaiting review thread on the nixos discourse or the matrix dev channel.

> The documentation of Nix and NixOS is rather poor. To understand how a service or an option works, it is very often necessary to read the source code (`.nix’ files) ...

I think this is also a plus point, for Guix and Nix, how easy you can check the parent file dependencies, which are the same language as the configuration you're creating, and are easy to understand

Except in Nixpkgs, where it's tedious to go from the package's expression (easy enough to find from NixOS Search) to where it's called in `all-packages.nix` or to the various helpers exposed in `lib`. But there are multiple efforts to make jumping to declarations easier in the new CLI and even to rearchitect Nixpkgs.
My main problem is that Nix is based on one version of libc. If your system already has vendor-locked libraries based on a different version of libc, then it is quite difficult to get the rest of the system on that same version of libc.
What systems have you encountered this on? (just curious; not trying to minimize)
Arch Linux. I have to use Nix for a project and it broke almost every time Arch updated its glibc which made it a pretty horrendous experience.
This should be fairly straightforward with overlays (https://nixos.wiki/wiki/Overlays) right? Just overlay libc package with the version you want to use.

The main disadvantage of doing this is that you lose the binary cache and will need to rebuild your system from scratch. This will eventually be solved (content-addressable packages), but that needs reproducibility guarantees that current compilers don’t provide.

Regarding the second point, ("it's not enough to have the same /etc/nixos/configuration.nix file, because of environment variables, other files, and commit revisions of repos used"), this is one thing which Nix Flakes solves.

With nix flakes, all the Nix sources you use must be checked into source control, and impurities like environment variables can't be used (by default).

This is actually the opposite, by default, impurities like environment variables can still be used, as well as binaries, or other things !

A small example :

```

[remy@typhoon:~/Blog]$ cat flake.nix { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11"; };

  outputs = { self, nixpkgs }:
    let pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in
    {
      devShell.x86_64-linux =
        with pkgs;
        pkgs.mkShell {
          buildInputs = [
            python3Packages.pelican
            python3Packages.markdown
          ];
        };
    };
}

[remy@typhoon:~/Blog]$ export HELLO="WORLD"

[remy@typhoon:~/Blog]$ nix develop

warning: Git tree '/home/remy/Blog' is dirty

[remy@typhoon:~/Blog]$ echo $HELLO

WORLD

```

And, because flakes are not stable, you need to enable them with e.g. `--experimental-features 'nix-command flakes'`. And by default, you can still access outside binaries, like let's say ls ! Which is why, to have real hermetic builds, in Guix for example, it's advised to run in containers and so on.

> by default, impurities like environment variables can still be used

In a `nix develop` shell? Ah, sure. -- I don't think the new nix commands have the same functionality that `nix-shell --pure` had.

But, in nix expressions used, in order to use environment variables (or to fetch from URLs without using a known sha256), the `--impure` flag needs to be passed.

A dev shell is designed to allow the outside environment to be accessible (so you've got access to tools you'd want to invoke while working that aren't strictly project dependencies).
The dev shell inherits environment, but the builds don't. Having a dev shell inherit none of your environment is possible but an inconvenient default, you can do this with `--ignore-environment`.

`nix build .#somePackage` is pure by default, as is `nix flake check`

I believe `nix shell` also inherits environment by default for the same reason. People expect to be able to run the packages they installed system wide after entering a shell.

Slight misunderstanding in the blog post there.

> Archlinux is 78% reproducible on amd64 packages

> Debian is 95.7% reproducible on amd64 packages

This references the "fuzzing" infrastructure hosted by the Reproducible Builds project, and doesn't show "true" reproduction of binaries. It's designed to help us figure out where impurites occur in builds.

Proper package reproduction is much better in Arch because we don't have to care about all differences that can occur since our build systems are mostly static.

The true number hover around 86%-90%, which is better than the CI system.

https://reproducible.archlinux.org/

The main issues here is regressions in compilers, build tooling and leaky abstractions that needs to be found and patched. An example is how i spent a month tracking down a gcc bug that caused cgo builds to be unreproducible.

https://go-review.googlesource.com/c/go/+/413974

Thanks for the details, i'll update the numbers for Arch !
> This references the "fuzzing" infrastructure hosted by the Reproducible Builds project, and doesn't show "true" reproduction of binaries. It's designed to help us figure out where impurites occur in builds.

I think the "fuzzing" approach is actually the correct one. The fact that build systems are static does not improve reproducibility on its own, as the idea is that the packages could be built on different systems and result in the same binaries. If I built some Arch PKGBUILDs from the official community repo, I should still get the same binary, despite the fact that my machine has a different setup from the Arch project's own infra.

The article mentions Guix several times but never once mentions as a pain point that Nix lacks a well-founded programming language.

Now I may be a total outlier here but it seems to me that while getting the fundamental concepts right is a good thing, having powerful means of combining them becomes more important in the long run.

Does that not speak in Guix' favour?

It does for Guix, but it's not such a big deal in my opinion regarding Nix. Please note I didn't think about this in depth, but, yeah, of course, using Haskell or Ocaml would probably be cooler than some domain specific language. But I also believe the nix language also makes Nix more accessible at first than let's say Guile : entering into the Guix world is certainly more costly, and I feel Nix* capitalizes on this lower entry bar.
Haskell would have been a mistake. The Nix language is domain specific and self limiting and can be picked up pretty quickly in comparison. I can look at snippets in various configs and they will usually have a similar structure. If Haskell was used, then you'd find all kinds of custom operators and other more complicated things that make it really hard for beginners to understand. I switched from XMonad to Sway for this reason.
You actually can search repos in their entirety on github now, think it’s a beta-feature you can enable or use. In other words, congrats, they’ve already indexed your entire codebase because they needed to for copilot.
I agree with all the points in this post.

And, I love NixOS. It's really special and very different than the other Linux I've used for 20 years.

I have been curious to try Guix at some point. Does anyone know if there is a good comparison write-up?

Also, can anyone speculate why the community has had such a hard time documenting this incredible technology? There are great posts like this from Xe: https://xeiaso.net/ but not generally getting started guides that are up to date. Why is this so hard to do? I mean, I'm not doing it because I personally feel like everything I do to get something working on Nix is a quasi-hack and not the standard and most up-to-date way to do it, so I'm hesitant to share. But, surely there are experts that like to write. Is this a problem with a simple technology solution (choose a better documentation tool)?

I think the issue is that there's just so much to document. I worked my way through the Nix pills, and understood the language and philosophy. But then doing anything productive with it is just way bigger than I can get my head around. It's like the joke about drawing an owl: https://i.imgur.com/rCr9A.png
Realistically, the nix community is made up of a lot of functional programmers. I realize the nix language seems confusing to many, but to fp programmers, it's intuitive and there's not a whole lot to say about it.
The main problem of nix is not even the nix language, though I've heard little good around its error handling and debugging. My admittedly shallow understanding is also that it doesn't matter that much because most of your time will be spent in the sprawling mess of nixpkgs.

> it's intuitive

The naming is very odd (e.g. why "sets" for dicts / records), and then it manages to make the language incompatible with itself by having attribute sets for values and a completely different syntax for attribute set parameters, no doubt because the language was ambiguous due to the lack of function prefix (also makes curried functions awkward).

Like, there's nothing hard to it, but the entire language feels awkward for no reason. Like "?" meaning "default value" in parameters but "has attribute" for navigation (where "or" is "default value").

> I realize the nix language seems confusing to many, but to fp programmers, it's intuitive and there's not a whole lot to say about it.

XSLT is also a functional language. That doesn't make it not-awful.

> The naming is very odd (e.g. why "sets" for dicts / records), and then it manages to make the language incompatible with itself by having attribute sets for values and a completely different syntax for attribute set parameters, no doubt because the language was ambiguous due to the lack of function prefix (also makes curried functions awkward).

It's not sets... It's attrsets, and the naming of the construct doesn't matter. I'm not sure I called them anything until I looked it up just now.

As for syntax... I'm not sure what you're referring to. Pattern syntax and construction syntax are different in every functional language I know.

> XSLT is also a functional language. That doesn't make it not-awful.

You're thinking of XQuery I think

Nix broadly borrows exactly everything from the lambda calculus, with no change in terminology. It introduces records, which is kind of necessary for any serious programming. It adopts standard conventions for records (curly braces and an equal sign). The only 'surprising' bit of syntax is the lambda construct, but this is such a minor thing it's almost silly to complain about it. I honestly don't understand what is surprising about the nix language.

Nixpkgs... sure I can see that, and I actually agree that types would be nice. Or at least interfaces. But the nix language as a whole is pretty straightforward.

> It's not sets... It's attrsets

You may want to tell, er, the official website? https://nixos.org/manual/nix/stable/language/index.html

> { x = 1; y = 2; } A set with attributes named x and y

> and the naming of the construct doesn't matter.

It absolutely matters when you're trying to learn the language and the naming of concepts is nonsensical.

> Pattern syntax and construction syntax are different in every functional language I know.

So you don't know Haskell?

    -- construction
    example = Person { name = "John Doe", admin = True }
    -- pattern
    render Person { name = name, admin = admin } = name ++ suffix
      where
        suffix = if admin then " - Admin" else ""
or OCaml?

    (* construction *)
    let initial_state = { lcd=0; lka=Equals; loa=Equals; vpr=0 } ;; 
    (* pattern *)
    match s with
    | { lcd = a; vpr = d; _ } -> (* Expression *)
or Rust?

    // construction
    let p = Point { x: 0, y: 7 };
    // pattern
    let Point { x: a, y: b } = p;
All three have punning (as an extension for Haskell) so you can skip the explicit rebinding, but that's not what Nix does, as far as I can tell it doesn't have punning on the construction side, doesn't have full syntax on the pattern side, and the syntaxes are just similar enough to be annoying:

    # construction
    { x = 1; y = 2; }
    # pattern
    { x, y }: x + y
> You're thinking of XQuery I think

No, I am not.

> I honestly don't understand what is surprising about the nix language.

I can only assume that's Stockholm syndrome given I literally just went through https://nixos.org/manual/nix/stable/language/index.html and found the inconsistencies listed above, also that @ patterns can go on either side (why?), or the existence of "with" (though I guess in a functional and pure language it's not as bad as it is in good ol javascript with which it shares this great feature).

And it's not that it's "surprising", it's just that it's... sloppy. Sub-par.

And definitely not "intuitive". Even less so when a pair of single quotes is equivalent to a double quote (except not), rather than either an empty string (or at least something string-like), or an error. To say nothing of the escaping scheme inside those string literals.

No,he is correct when he says XSLT. It's a pure functional language with a terrible syntax.

Nix as a language is fine. There isn't actually much to it. However the extreme approach to laziness while quite powerful also means you can't actually follow the flow of a package. It's manifests as come from programming since with stuff in packages with no reference in yours messing with your own packages internals. It is possible to tease it out and after a while you sort of know where stuff is probably coming from. But even for someone who is pretty comfortable with Haskell and other poster children for FP, nix is a challenge to reason about code locally.

Perhaps because there isn't really a starting point for this?

Different people use nix for different things, perhaps a bit differently (e.g. whether they use flakes, home-manager, what channels do they follow). Each language has their own way of building packages, and different 'framework' in nix to build for them (usually about how to pull the dependencies in a reproducible way). And there are things that readers are expected to know such as basic shell scripts, paths, etc.

I don't think Xe's posts are all that great. The stuff they complain about are a result of not knowing what Doom Emacs does for them (because Henrik Lissner uses NixOS personally and has added a lot of convenient functionality to the nix module).
It's too late to edit but I'm speaking specifically about their guix/gnu posts. Otherwise they're fantastic to read.
https://devenv.sh/ covers most of these points as none of the complaints mentioned are design flaws, but they are just something we have yet to reach.
Been using nixos for about a month. It took me about a week to really start to grok Nix a tiny bit, I had to spend a lot of time on the forums asking questions or searching for questions because the discoverability of the documentation is low when you don't know the lingo.

I'm loving it now though, I have 3 computers running it and a flake that I push to github. I can push changes to my flake and have all my systems reflect the changed with a quick nixos-rebuild. Also being able to roll back is invaluable.

I reformatted one of my systems the other day and it only took about an hour to have my whole system in the exact same state it was before with all my tooling and files.

> It took me about a week to really start to grok Nix a tiny bit, I had to spend a lot of time on the forums asking questions or searching for questions because the discoverability of the documentation is low when you don't know the lingo.

Do you have resources you would recommend on that front?

Having to go to forums over and over and hope a kind stranger will take pity doesn't seem scalable.