Brian Lovin
/
Hacker News
Daily Digest email

Get the top HN stories in your inbox every day.

tikhonj

I've been using Nix and NixOS for a while and I've seen four core advantages:

1. Nix store: what the article covers: multiple versions of the same package, "virtualenv for everything"... etc

2. Reproducibility: because package definitions are self-contained, I can pin and reliably reproduce everything for my packages. And I do mean everything.

3. Flexibility: Nix works for system packages on NixOS as well as user packages on any Linux or macOS. I've been sharing like 70% of my system config between Linux and macOS, and I don't know of any other tool that can do that.

4. Programmability: package definitions and config are extensible and composable. Yes, learning an ad hoc language to do this is a pain, but once I learned it I got a higher-level and better-abstracted way to define and combine packages than any other tool I've used. It's like going from C to OCaml. At this point I've started hating Dockerfiles because they can't easily be composed and don't provide any real facilities for abstraction.

Ultimately, Nix took system management from feeling like an operational activity—maintaining and changing a bunch of mutable state to run the system—to declarative programming. Learning curve aside, making system management a reproducible programming activity with no system state to worry about has been a massive improvement.

throwaway894345

I've tried to use Nix on and off for years. I always run into issues where I need to write some package and

(1) I get mired in packaging low level transitive dependencies and things which seem like they should be easy end up being nearly impossible

(2) Basic things like figuring out the argument types for a particular nixpkgs function take an insanely long time. It always involves grepping around the whole repo (nixpkgs is huge for those who don't know) for invocations to find the variable that gets passed into that function and then grepping around the repo for the function that produces that variable and so on until you get to the source type. Things have awful names and documentation is sparse.

I'm a big believer in Nix as an abstract concept, but the execution has been a miserable experience for me to the extent that I can't make sense of people who report such positive experiences. I would think I'm doing something wrong, but so many people have corroborated my experiences and when I bring specific issues to experienced Nix users they also get stuck.

Ultimately, I've reluctantly gone back to dealing with Docker and system package managers because their failure modes are rarer, more predictable, and more easily worked around.

EDIT: and I haven’t touched on the problems associated with using Nix in an organization. It seems like invariably one or two people become “the Nix experts” and they become the bottleneck for the whole organization, every team needs to coordinate virtually every interesting activity with them, etc.

utdemir

As someone who is using NixOS for 8+ years, I do agree with both your problems.

(1) I do find that it's very rare having to implement a low level transitive dependency from scratch (most low-level system dependencies are already there, and for dependencies of a specific programming-language ecosystem you'd usually auto-generate them from things like `yarn2nix` or `poetry2nix`). However, I agree that once you need to do that for non-trivial library it quickly becomes painful and require intimate knowledge of both the build system and Nix environment.

(2) This is my main issue. My workflow is also having a local `nixpkgs` clone, and go find the function and the parameters I can use every time I don't remember how to use it. I also think that it is sustainable. There are many exciting improvements going on with the new CLI, so hopefully we will get nicer error messages and better tooling support in near future.

> but the execution has been a miserable experience for me to the extent that I can't make sense of people who report such positive experiences.

There are pain points, but the advantages for me were indispensable. Being able to pin dependencies accurately, reproduce an exact development environment deterministically, and use the single language to define applications, configurations, and even entire system images is a great benefit that I would need to use 10+ tools with individual quirks otherwise.

nextos

Have you looked into Guix? In some ways it's a bit simpler and cleaner because it is a much more recent effort and Scheme is somewhat easier. It might help with the learning process in case you disliked Nix. GuixSD does have some other drawbacks. I'm personally running NixOS but both are very cool.

Nix certainly has a steep curve, but simple things are not that hard. I got committed to migrate to Nix one Monday. I spent the whole morning reading about it. In the afternoon, my workstation was already up and running. On the same evening, I packaged two exotic things I need which weren't on NixPkgs. Next day, I fixed my favorite window manager, which was broken on NixPkgs. I maintain all these on NixPkgs now.

Complicated things are not that easy, and I would not have been able to do all this if I had encountered non-trivial issues in the process. I also totally understand that the learning curve is steep. Nix has too much legacy stuff and cruft built in. There's the classic Nix command, Nix 2.0 and Nix flakes. They are all coexisting and not very well documented. Nix needs more manpower, funding and tooling.

With that said, declarative stuff is poised to be harder for non-trivial stuff. Just like Haskell is harder than C, NixOS is harder than ArchLinux or Alpine. I still very much find it worth the effort for simple workflows. I can now update remote machines without fearing breakdowns and state is very explicit.

PoignardAzur

> Nix certainly has a steep curve, but simple things are not that hard. I got committed to migrate to Nix one Monday. I spent the whole morning reading about it. In the afternoon, my workstation was already up and running. On the same evening, I packaged two exotic things I need which weren't on NixPkgs. Next day, I fixed my favorite window manager, which was broken on NixPkgs. I maintain all these on NixPkgs now.

I mean... it's great that you did all that, but you do realize that going that far makes you a power user, right?

Most users are going to give up if they can't figure out how to install their window manager or other essential software (eg installing Docker or Steam is ridiculously hard if you don't know that they have special hard-coded config values; it's almost like a game you can only beat if you find the cheat codes).

> With that said, declarative stuff is poised to be harder for non-trivial stuff. Just like Haskell is harder than C, NixOS is harder than ArchLinux or Alpine. I still very much find it worth the effort for simple workflows. I can now update remote machines without fearing breakdowns and state is very explicit.

Hard disagree. I could totally see a world where NixOS is as easy to install as any other distribution. But the developers are going to have to put a lot of work into smoothing out wrinkles before it gets there.

petre

I've tried a bootable vm image but couldn't figure out how to configure, the docs only cover the installer, no examples, so I gave up. It seems like it's a Guile recipe for an OS. I want the OS with docs, examples, maybe a simple instalker to get everything bootstrapped. Then I could learn to write recipes. Other than that, Guile is attractive and so is GNU Shepherd, which is why I tried it in the first place.

tikhonj

Yeah, I've had that similar experience too, and I'd love to see an approach that can fundamentally improve on this axis.

The way I see it, it's the foundational ideas that are important—but there are a few key principles beyond the one covered in the blog post.

Separately, today, I think the foundational advantages Nix has more than justify the learning curve—but that's a less obvious idea and I understand why it's hard to convince other people about it :).

cwp

The trouble is that it's the foundational ideas that people find weird and difficult. Functional programming is still niche and so both immutable package installations and nix-the-language don't build on what people already know.

I hope that'll change over time, because yeah, the foundations are /so/ powerful, even today.

pmarreck

Exactly what I've found. The concept is brilliant. The execution is user-hostile. I wish someone brilliant would take a good look at it for a long time, then head off into the tropics for a month while meditating on how to simplify it and/or make it more user-friendly, and return with something that is equal to Nix in concept but superior in execution and UX.

takeda

> (1) I get mired in packaging low level transitive dependencies and things which seem like they should be easy end up being nearly impossible

this is most painful, because a lot of packages do tons of tricks that make it very difficult to get reproducibility. Like downloading dependencies at build time, non standard places of installing things hardcoded paths etc.

If you are tried cross compile arbitrary packages it might be familiar. A lot of projects don't know how to do things correctly, or doesn't care and just want their code to work.

To that, other environments have their own quirks. For example the way most nodejs applications work they do expect their dependencies in current working or parent directory.

All those things require some patching. If you can get the patch upstream that's awesome, otherwise you'll have to maintain it.

What is great about other distros, is that if you try to use some exotic library, you can just try things randomly until you get it compiled and installed in /usr/local :)

Imagine if you had RedHat installed, and it would impose that you can't run anything unless it's packaged in rpm. If you would have to prepare a .spec file and run rpmbuild command. I bet experience wouldn't be far off.

Unlike RedHat Nix does force this and this is a double edged sword. It creates this pain, but on the other hand it forces some kind of order.

BTW: if you want it hard enough you can still install packages the traditional way (but likely would have to specify --prefix to somewhere inside /home than /usr/local)

lallysingh

The problems are twofold:

1. The language is a significant problem. If you get everything right, it will do what you want. That's the only nice thing I can say about it. Almost every error it will give you will be misleading. I haven't had such a hard time figuring out errors since early C++ template metaprogramming. And frankly, that was easier.

It needs real diagnostics, and that frankly, that means it needs real types. But that won't happen. Too much of the informal type system of nix is "whatever keys that library function uses, go look in the source."

2. Half-implemented packages. Try walking out of the golden path on a package, without having to modify its nixpkgs entry.

Between the two, it's more nerd-bait than usable platform.

takeda

Looks like these things are being addressed, although from past of experience it probably will take several years :( (when I started using Nix, 3 years there was a talk about this new thing called flakes, now the version 2.4 already contains it, but it is still locked behind experimental features)

1. https://github.com/tweag/nickel - it is a typed language, that might in the future replace nix language

2. looks like likely is addressed by flakes

mikepurvis

"... with no system state to worry about"

I don't disagree with you, but one of my skepticisms about this is that Docker and Dockerfiles made the same promise like eight years ago, and at least as a small time operator (eg, homelab), it never really felt like the system was as stateless as it was telling me it was. There were always logs, indexes, caches, database content, and all the rest of it, and all of this had to be carefully volumed-out with those data containers being protected and versioned and carried forward independent of the throwaway Dockerfile-defined "application" containers.

So far my experience of NixOS is that it doesn't particularly offer a new solution here, but at least it doesn't pretend anything. The configuration.nix "defines" the whole system, but obviously doesn't touch anything in /home or /var, so that's on you to back up, migrate, whatever.

throwamon

> The configuration.nix "defines" the whole system, but obviously doesn't touch anything in /home

https://github.com/nix-community/home-manager

> or /var, so that's on you to back up, migrate, whatever.

https://grahamc.com/blog/erase-your-darlings

https://github.com/nix-community/impermanence

tomberek

You can't get rid of all state. The pros/cons of a Nix approach is that it is far more explicit about what is pure/impure. This experience is similar to going from a dynamically typed language to a stronger type system; it can be frustrating to be told that something is not allowed. Nix's usability difficulties often come from trying to build or use software that violates purity in some way (reading HOME directories during compilation, using the network in some way, assuming a dependency will "just be there"); it prevents these mistakes at the cost of forcing the person doing the packaging to fix these issues. This is a huge benefit in the long-term, but can annoy short-term uses.

jancsika

I'm so confused-- there's a user upstream reporting something about having to grep for a variable name, then having to grep for the function that created the variable just to figure out the type.

Are they using Nix wrong? Or is this seriously a limitation of the current state of the tooling?

If it's a limitation of the tooling, that almost sounds like satire. I.e., someone builds a powerful functional DSL, uses it to painstakingly construct a monstrous package graph, then gets tired and wonders, "Wouldn't it be great if there were a language and data structure that were both custom suited to automating the grep'ing of argument types for my DSL's package graph..."

mikepurvis

Many of the necessary fixes do end up getting pushed upstream, though, thinking especially of stuff like converting CMake projects to use the GNUInstallDirs standard, so there is a benefit to the strictness work that extends beyond even just the Nix community itself.

Of course, sometimes those kinds of changes just never get merged, for a variety of well-understood open-sourcey reasons, eg: https://github.com/pocoproject/poco/pull/3105

tikhonj

That's true. I guess I see it as the difference between the system and what I'm doing with the system—it's like having a database system where I'd want the config for the database to be totally reproducible and immutable, but I'd expect to manage the data itself separately.

And, as a practical benefit, I found setting up borg backups for /home on NixOS a lot easier than I expected :)

mindslight

I think your reasons are focused on Nix for package management. For NixOS specifically, I would add:

5. It's essentially a source distribution with caching. If you want to add say a kernel patch, or any other type of patch, it's straightforward. Whereas running Debian and finding the solution to some problem is building a modified package, my usual conclusion was just to bear the problem until it was fixed upstream, rather than suffer the maintenance burden.

6. The top-level config is front and center, and stateless. No messing about with update-initramfs, wondering what the heck the initrd is actually doing etc.

7. Taming the complexity of system software's configuration state. For example, there is no mucking with the systemd mess of /etc/systemd vs /lib/systemd and its assorted symlinks, as this configuration is handled at a higher level.

And for Nix I'd add

8. Dead simple cross (or emulated) compilation toolchains. Building A Cross Compiler used to be a Big Deal, with Nix it's basically like any other declaration to build an entire cross/emulated environment.

xorcist

Building packages from scratch for Debian can be a hairy endeavour, lots of tooling and it can be hard to know which one to use.

But building packages for Debian is dead simple, it is literally one command. Adding a patch to an existing package, and then rebuilding it, is a common operation.

mindslight

I've run Debian for two decades, so I've definitely ended up going down the path more than a few times. Yes, the actual building process wasn't so hard. It was the maintenance burden afterwards. Maybe I just didn't commit hard enough with my own apt repo, pinning, staying ahead of what was coming through backports, etc. But point is that it effectively never stuck long term, the end result was always going back to vanilla upstream. Whereas in Nixos such patches are some lines in the larger config file, which feels a lot more persistently manageable.

dimsuz

Whenever Nix/NixOS gets discussed I always see same points being brought up again and again. And again. I've never seen anything which is discussing solutions or the roadmap (however distant) to solve those issues.

Can it be that nothing is happening in this regard or is that really so that people only list same cons over and over again? :)

otabdeveloper4

It's like complaining about C++. It will always be there. Ignore it, it's just people venting about the fact that solving hard problems is hard.

kitsunesoba

Did they ever fix the need to disable SIP for nix to work on macOS? That made trying it out a nonstarter when I looked into it 2 or 3 years ago.

takeda

I started using Nix around 3 years ago, and I actually didn't encounter this issue. The last issue was when Catalina made root read only, there is some hacking to keep /nix in the root.

Edit: after searching about it, looks like this was the same issue with /nix in the root, and disabling SIP was one solution at the time. Currently the solution appears to be creating a separate volume and using /etc/fstab and /etc/synthetic.conf to set it up[1]. The installation script does it automatically.

https://nixos.org/manual/nix/stable/installation/installing-...

theptip

I hit similar issues a while ago, and I think they have this figured out now. The installer Just Works (tested on a MBP2015) as of a few months ago.

sandgiant

This mirrors my (very limited) experiences with Nix. I've so far only dipped my toes in home manager, but being able to share shell config and cli tools declaratively between WSL, linux and MacOS with very little branching has been great!

amelius

> Reproducibility: because package definitions are self-contained, I can pin and reliably reproduce everything for my packages. And I do mean everything.

Does that mean we get downloadable precompiled binary packages too? If not, why not?

tikhonj

Yep. The cool thing is that installing a binary version of a source package is totally transparent from Nix's point of view—it's not a different entity, it's solely a matter of caching. If you're building a package that somebody else built and uploaded to a cache that you can access, you'll download the binary instead. There's a public cache, so when you use a standard package set as your base, you'll be getting most things as binaries. But if you make some changes or something else breaks and binaries aren't available, it falls back to building from source transparently—sometimes this can take a loooong time, but it usually doesn't, and I'd rather have the option to do that than not :).

The other bonus is that it takes very little effort to share your own binary cache—either privately (so that you or your company only need to build something once) or publicly (so that people installing your open source tool don't have to build from source). There's even a really well-designed commercial service called [Cachix][1] that provides a totally turn-key binary cache, including a free tier for open source projects.

[1]: https://www.cachix.org/

takeda

I use this for building system. Instead of Cachix I just set it up as an S3 bucket (it's a bit involving but also works). I needed to tweak some things but ultimately arrived to satisfying results.

The nice thing is that it sped up building by 50% and also extra bonus with things is that with merges, if files didn't change nix will finish building instantaneously.

This is similar with nix-shell, where for example with python you enter "virtualenv" like environment almost instantly without downloading dependencies over and over. Yes, you could get close to do that with CI by using some caching, but this is out of the box, due to nix understanding dependencies.

Also another great thing is that so far, I never needed to purge cache, which often happens with normal CI caching.

southerntofu

my understanding is that most nix/guix users don't compile (most) packages themselves but download them from a binary cache. why not would be for obvious security reasons but at least on the guix side there's a subcommand to compare build hashes from various mirrors you trust: https://guix.gnu.org/manual/en/html_node/Invoking-guix-chall...

avakand

I tried using NixOS on a laptop for a month and switched back to Arch a couple of months ago. It was an interesting experience - I never used functional programming language before, but nix was pretty ok as a configuration language. It looks like funny version of JSON with functions.

Debugging it was a real pain though - I was trying to write (or copy from someone else config) a function to recursively import all modules from a folder and the error messages were hard to understand with stacktraces ending somewhere deep in standard library.

The other problem was with nixpkgs, i.e. I haven't found a clear list of packages that were going to be updated. Jetbrains IDEA was updating very slowly and when I wanted to pin a version of it simply overriding version variable in the overlay was not enough - there were also some other linked variables. Emacs package from custom overlay constantly tried to compile itself, requiring me to check build status on hydra build system.

In the end I decided that it's not really worth it. I don't have many systems and services to manage and for a raspberry pi and a vps multiple docker-compose.yaml files in git repo is enough. I think Henrik Lissner (author of Doom Emacs) wrote a really good piece about why someone should choose to use NixOS - https://github.com/hlissner/dotfiles#frequently-asked-questi...

2pEXgD0fZ5cF

Same here, tried NixOS for ~3 months, I tried to go all-in too, I spend time to really read the docs and work out an intricate configuration that leverages features like flakes and covers my system setup and dotfiles (got inspired by Lissners NixOS configuration) and was ready to handle multiple systems in preparation to roll it out to my 2nd and 3rd machine.

Ultimately there were warts that I was able to solve, but still annoyed me greatly and felt ugly and forced me to step outside the convience of my nixos config system (like wifi with iwd, btrfs + swap files) and at one point I was no longer able to `nixos-rebuild switch --upgrade`, the command kept failing even on versions of my config that I was able to confirm working, I spent some time trying to find the problem but eventually came to the conclusion that it might not be worth it in the long run.

In the end I went back to my previous distribution of choice. I still find the whole concept interesting and I will give Guix a try next.

Fixing NixOS problems that the community hasn't encountered or solved yet really fills me with a special kind of dread compared to regular distributions where finding a solution to a rare problem is usually just a mix of taking a look at upstream and writing a patch or adapting general solutions from other distributions.

ris

I honestly think that Nix is one of those things where "going all in" is one of the worst things you can do. Running a desktop system on NixOS is quite a tricky prospect for someone with no experience of Nix and you'll likely get frustrated with having to learn some potentially alien concepts to achieve simple things.

I tend to recommend people start in the shallow end, using Nix on a regular Linux distribution (or even macos) for a while. Use it to manage development environments and for ephemerally accessing tools as you need them.

For me, the place that NixOS itself really shines is on servers.

mst

Being able to spin up an entire network of qemu+kvm VMs easily to do proper integration testing of my system configs was a revelation.

trexd

I found that building my configuration on a virtual machine was the best way to go. This way I was not desperate to get things working and simply moved when I felt like all my essential programs were in place.

amarshall

> I haven't found a clear list of packages that were going to be updated.

The ideal here, IMO, is to use flakes and the nix-diff to compare the build before switching. E.g.

    nixos-rebuild --flake '.#myhost' build
    nix-diff /nix/var/nix/profiles/system result
    sudo nixos-rebuild --flake '.#myhost' switch
Could do the same without flakes after the fact by running nix-diff on different generations in /nix/var/nix/profiles (there may be a way before switch). It’s unfortunate that how to do the above is non-obvious.

tazjin

There's nothing there that needs flakes (an experimental feature which people should not enable without understanding the implications). You could build a system derivation and run a diff against /run/current-system on it.

For what it's worth, nix-diff has very verbose output (it literally diffs everything that is different in the inputs & outputs). A slightly nicer way to diff systems is nvd[0] (example output[1]) which only shows version changes and added/removed packages.

[0]: https://gitlab.com/khumba/nvd

[1]: https://deploys.tvl.fyi/diff/4xmyvkr9nw0cwkn5q38p0cfc58x3jdy...

flurie

Flakes are "experimental" in the sense that gmail was in "beta" for however many years. I feel like it's important to mention that you're attempting to rewrite nix[1] and explicitly ignoring flakes[2]. Many people using nix are coming to the conclusion that flakes make things much easier to use and understand, and they obviate the need for a lot of secondary tooling that has become standard. There's an easy way to gauge support for flakes: look at how many high-profile nix repos have an up-to-date flakes.nix file.

[1] https://tvl.fyi/blog/rewriting-nix

[2] https://lobste.rs/s/ypwgwp/tvix_we_are_rewriting_nix#c_zvtze...

remexre

> experimental

Haven't flakes been non-experimental since 2.4?

avakand

I was using flakes, yes. I remember seeing nix-diff, but most of the time nixos-rebuild dry-build was enough. Sometimes dry build was failing with error, but switching or activating it ran without errors. Never figured out what was wrong :(

chriswarbo

> Jetbrains IDEA was updating very slowly and when I wanted to pin a version of it simply overriding version variable in the overlay was not enough - there were also some other linked variables. Emacs package from custom overlay constantly tried to compile itself, requiring me to check build status on hydra build system.

The way I solve this is to import multiple versions of Nixpkgs, since they're all self-contained.

For example, if I'm upgrading from Nixpkgs/NixOS 21.05 to 21.11, and I find that package 'foo' has broken, or been removed, I'll do this in an overlay:

    self: super: {
      foo = self.nixpkgs2105.foo;
    }
Where nixpkgs2105 is a pinned revision of the Nixpkgs repo, defined in another overlay. My current Nix config has pinned Nixpkgs versions going back to 2016. For example, here's a bunch of such overrides:

https://github.com/Warbo/nix-config/blob/master/overrides/fi...

At the moment I'm using niv to manage the pinned Nixpkgs versions (the 'repoXXXX' entries):

https://github.com/Warbo/nix-helpers/blob/master/nix/sources...

epage

Another problem I ran into is trying to figure out how each package wants me to define plugins. There are common examples for Python environments (Python packages are like plugins into Python) but when it came to other software, I was at a loss when digging into things, even after reading all of the general documentation.

rgoulter

"""The first is relatively simple: they developed their own programming language to do configuration, which is not very good and is extremely difficult to learn. The vast majority of people using NixOS do not understand the language, and simply copy/paste example configurations, which mostly works until you need to do something complicated, at which point you're completely high and dry."""

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.

jcranberry

It's been a while since I used NixOS, but I never really had an issue with the language. What was frustrating was in package solutions there were all these special functions which as far as I can tell were undocumented and I couldn't figure out what they could do. So there was sort of this gap in terms of documentation between theoretical understanding and tooling/functional understanding which I struggled to cross.

mikepurvis

As someone 8 months into a major Nix packaging effort (1200 package definitions, mostly auto-generated), this is 1000% the most significant issue. Reading the pills can get you the first little bit, like the difference between derivation and mkDerivation, but so much later stuff is just completely undiscoverable and inconsistent, like the fact that overrideAttrs may subtly not do what you want if it's a Python package since you have to use overridePythonAttrs instead, but the corresponding function for other builders (eg overrideBazelAttrs) doesn't exist.

FRidh

This is indeed not very good. Note there is a reason that overridePythonAttrs exists: it overrides the call to buildPythonPackage instead of mkDerivation. There is/was an RFC on standardizing overriding in Nixpkgs but it got stuck. I think for these things to improve what is really necessary is funding to improve Nixpkgs. These kind of issues are fairly hard to solve as they span multiple ecosystems and require coordination.

snowytrees

100% this. The language is designed for its use case which is packaging and configuration (nothing more or less). It has a learning curve due to being lazy and functional but works great once you get the hang of it. But the documentation of all its functions is so annoying. You have builtins and the nixpkgs functions[1]. There is learning the language, and then learning how to use it. Then there is the entire ecosystem of custom packaging functions that have their own pros/cons [2]. The issue isn’t with the language but the difficulty with trying to make existing tooling work the Nix way. That part is where I agree with the curse of nix. But the effort is worth it because once the packaging is complete it just works (forever).

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/...

zeec123

However, until this works, nixpkgs should provide a wrapper around FHSUserEnv which allows developers to develop without the curse.

jcranberry

These look pretty promising. Maybe I'll give nixOS another shot because I really was a big fan.

mplanchard

The best way I’ve found around this is to always keep a local clone of nixpkgs so that I can grep for where functions are defined and hope like hell that there are some comments in the vicinity. Definitely not ideal.

rgoulter

If you're using Nix on your system, you can also find nixpkgs symlinked under ~/.nix-defexpr/channels/nixpkgs/pkgs/ or so.

zeec123

What really helped me were the videos of Jon Ringer: https://www.youtube.com/user/elitespartan117j27

jonringer117

Glad someone found them useful :)

takeda

I believe what Nix really, really needs. Is to separate all the lib, builders and frameworks for languages need to be separated out of it (probably into separate repo, maybe even repos), and treat it like a stdlib is treated in any other language.

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.

zeec123

Fully agree. It is not the language, but the functions around nixpkgs.

TheYumasi

> Maybe that is difficult for people who haven't had an experience with pure/functional programming?

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.

jonringer117

All builtins functions can how render doc with `:doc` in the `nix repl`. I think there's work to make this possible with any arbitrary function.

ghostwriter

> 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...

kstenerud

The other problem is the condescending replies from the higher tier nix folks while everyone else struggles. I almost think they garner a sadistic pleasure in watching everyone fail.

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.

rgoulter

Nix is wonderful, but absolutely is under-documented. (In part due to a small community, etc.).

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...

undefined

[deleted]

JamesSwift

I was definitely in the "I just dont get it" camp for a couple years before coming across a comment on HackerNews pointing to Burke Libbeys fantastic playlist on Nix [1]. It was a revelation and was what I needed to finally have the DSL click for me. Cant recommend it enough.

[1] - https://www.youtube.com/playlist?list=PLRGI9KQ3_HP_OFRG6R-p4...

jerdfelt

Is there anything that explains the why and how a bit deeper?

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.

JamesSwift

I would watch the entire thing in order to get the "full experience" of his tutorial. This touches on things like the CLI vs just syntax.

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...

nvarsj

For me, nix the language itself is not that bad. It's all the magic happening in nixpkgs and the tight coupling there with the user interface (configuration.nix, shell.nix, etc.).

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.

ashtonkem

> 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?

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.

ghostwriter

I've programmed professionally in Haskell, I find Nix the Language to be one of the nicest DSLs for defining build pipelines. It's lazy, pure, and it's sandboxed. Whenever you need types on top of it you just pick Dhall and dhall-nix and continue with a productivity gain.

kaba0

Wow, I just commented that dhall would probably be a fruitful language to consider for nix! And it seems to exist, though according to the readme, general recursion, not strongly typed code and row polymorphism is not supported by dhall but is used heavily by nix :/

Do you by chance know whether a non-Turing complete language like Dhall would be enough to “replace” nix?

mindslight

The semantics are simple and necessary, yes. The syntax is kind of crap in some ways (in others it's awesome and I wish other languages were as lightweight). Syntax in general is a bikeshed, but that doesn't mean we can't objectively critique things like having function definition being a mere ":". That one on its own is probably responsible for much of the indecipherability.

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.

rnhmjoj

> overrideDerivation/overrideAttrs/override, I still don't fully get

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.

mindslight

Ah, I had forgotten `override` is easy. Rereading that page I still don't get the difference between `overrideAttrs` and `overrideDerivation`. `overrideAttrs` is newer and preferred, yet it doesn't spell out where you cannot use it and have to fall back to `overrideDeriviation`. And looking through my Nix code I've got various uses of `overrideDerivation`, which most likely means I tried `overrideAttrs` only to have it not work, so I tried the "deprecated" version and it did.

octoberfranklin

> the Nix language is about as straightforward as "JSON plus functions".

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.

jonringer117

> It's not a hashmap, or a map, or an object. No. It's an attrset. Riiiiight.

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.

octoberfranklin

> > It's not a hashmap, or a map, or an object. No. It's an attrset. Riiiiight.

> 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.

undefined

[deleted]

epolanski

Isn't a stable ordering just an n-tuple of pairs? Or is it more like a hashmap you access in O(1)?

chriswarbo

> It's not a build script, it's a derivation.

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.

rgoulter

> It's not a build script, it's a derivation.

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.

patrec

Yeah, naming a key-value data structure `set` was a really poor choice. A derivation isn't really a build script though.

octoberfranklin

Fair enough, but prepending an adjective to "build script" would still have been a much better choice.

Like "elaborated build script". Or "transitively-hashed build script".

kaba0

Seeing that the nix language was influenced heavily by haskell, perhaps Dhall would be an interesting “port”/change for the project - it is a deliberately non-Turing complete configuration language with types (but heavy type inference) and functions.

Because let’s be honest, types are user documentation as well, and the project would benefit greatly from the latter.

kaba0

Can’t edit anymore but this more or less exists already: dhall-nix can convert from dhall to nix, but unfortunately not everything done in nixpkgs can be converted clearly into dhall (due to nixpkgs’s use of some non-strongly typed parts and general recursion)

lallysingh

This post is dead-on. I've been trying nix in different forms for years, and it's been incredibly painful. The way the folks who use it normally talk about it is so different from real-life use by non-experts it feels like gaslighting. I only felt vindicated when reading https://ianthehenry.com/posts/how-to-learn-nix/ -- it's not me it's them.

Maybe one day it'll get good enough to be usable. Right now it's a long, long fight to get productive in any non-trivial (e.g., explicitly supported and documented) configuration.

res0nat0r

I've been messing with GUIX, just because the configuration language is much less confusing to learn and understand.

stabbles

You might as well try Spack, it's Python + a dsl to customize builds in a single line. Guix package descriptions look very daunting to me.

[1] https://github.com/spack/spack/

parasense

I used to think the ideas of NixOS were great, but then I learned about `ostree`, and in my opinion things like Project Atomic (in Fedora), are probably more pragmatic or straightforward idiomatic implementation of those ideas. In essence the software packages resemble how git works behind the curtain.

Git has a bunch of objects with cryptic names resembling hashsum's, and those are the files in your git working tree, they are sorta symbolically linked into the working-tree of the git repo. In the case of ostree, the working tree is a filesystem path such as the root of your filesystem. You can checkout a branch of the root filesystem on bootup, etc... and it's great for A/B testing because if there are any problems one simply boot into the previously known-good branch, etc.

The problem there is people sorta hate having to reboot after modifying the HEAD of the ostree repo, which might conceptually resemble a git commit into the main branch. Flatpak to the rescue, which is itself another implementation of `ostree` but not for entire root fielsystems, but for the package's filesystem layout, what you might think of as the contents of any given nixos package path. The same kind of things happen, bundle libraries can be different in different runtimes, and multiple runtimes can co-exist, and their file objects are deduplicated, and shared or isolated. The configuration language is JSON, so it's easy to manage as a packager.

CameronNemo

You can checkout a branch of the root filesystem on bootup, etc... and it's great for A/B testing because if there are any problems one simply boot into the previously known-good branch, etc.

You can also do this with NixOS, or even ZFSBootMenu.

discardedrefuse

Not just ostree. Using butane / ignition configs to setup coreos is very nice.

parasense

Sry for the necropost, but... I just started working on coreos at $dayjob. So your comment struck a nerve, but in a totally good way! :-)

I'll checkout butane / ignition ASAP.

Thanks!

Ericson2314

I understand the first complaint but not the second

> The second flaw is that NixOS does not actually provide real isolation.

I thought this would going to be about security, but then it was about having to repackage the world. But Nixpkgs is current the biggest and most up to date package repository in the world (we finally beat AUR). Packaging enough stuff is emphatically not the problem.

What I want to see is development be easier with Nix, because winning over the hearts and minds of upstream developers is the final frontier. To that end I wrote https://github.com/NixOS/rfcs/pull/92 and https://github.com/NixOS/rfcs/pull/109.

As a side benefit, autogenerating more Nix means less handwritten Nix! I do think people give the language itself to much grief when the problem is more the library side with the copious override shenanagins and other stuff.

tuetuopay

I think you missed the key point. Software needs to be altered to run on Nix, and it needs to do so _systematically_.

Grab a script from the internet? Edit the shebang! Download some prebuilt software? Good luck finding /lib/ld-linux.so.2! Need to use some proprietary software you cannot edit? HALP!

Of course there must be some tooling to get around this, since stuff like steam is available (at least I hope), or else anything not packaged by nix would be a nightmare to install and use as a user. Any niche or domain specific software would become unusable. Take for example Quartus II or Vivado (just to name the two top FPGA EDAs), those two are not packaged by nix. Yes, there are a few recipes floating around, but those honestly scare me enough to not want to do it with more obscure tools like those for other, smaller brands, FPGAs.

(disclaimer: I never used nix, but that's my understanding from the article, and my own experience running proprietary stuff)

Ericson2314

Hehe Quartus II is terrifying. It is like 10s of gigs of basically it's own distro. I have seen it showhorned into Nix but at the end of data it's a garbage heap of a "package".

Nice example :)

Yeah for me it's just more interesting to attack the problem at the root: developer UX, autogenerating packages from things like Cargo.toml, etc.. Prebuilt binaries is not something I really care about that much, and are existing tools do handle it quite well surprisingly automatically .

It's linux, if you are using some rando prebuilt binaries (not your distro's, or other trusted build artifacts cache) it's always a tragedy.

kwohlfahrt

I actually added Quartus Prime in nixpkgs a couple years ago! Haven't gotten round to the 2021 update, but that should get rid of the annoying 32-bit dependencies.

[1]: https://github.com/NixOS/nixpkgs/blob/1e643a385290e54947594a...

aidenn0

I suspect that the FPGA EDAs should run fin under steam-run. Packaging up giant balls of binaries is a mess.

sicariusnoctis

Side note: It would be nice to have a way to look up library -> package name.

tikhonj

> I do think people give the language itself to much grief when the problem is more the library side with the copious override shenanagins and other stuff.

I sympathize with this, honestly—the separation between Nix the language and Nixpkgs the library/codebase is just an implementation detail from the point of view of the user. This is especially true for core constructs like overrides—overriding is a pretty fundamental abstraction that would be part of a differently designed language, so the fact that it's more like a Nixpkgs convention is not going to be clear (or particularly useful) to somebody learning Nix.

Ericson2314

I think you have the mindset right, so thanks for elucidating that. I would still push back.

Ultimately library + language is serving a single goal here, but "means to an end" != mere implementation detail!

As a user of a language, it's incumbent upon you to learn the difference between library vs langauge in what you write. Full stop. I do wish Nixpkgs would be less rediculous. I wish there was a GUI too! But people who are going to write some code still need to learn the difference between language and library way.

Ultimately I don't think a more mainstream language would even help with the override soup problem, and we will need a logic programming type thing, but that's a separate point.

colinramsay

> I'm going to keep using it, since I can't stand anything else after having a taste of NixOS

This is how I feel about NixOS. I like what it gives me but I don't really like much else about it. Unless something _just works_, you're looking at hours of debugging which will most likely lead to failure. Off the top of my head there are a couple of things I've hit a dead end on recently:

- Packaging a Flutter desktop app because its build process downloads fonts from a URL and so makes the whole thing impure

- Getting Blender's GPU support working, I think the same problem is causing Webcamoid to crash on launch

Previously I used Arch, which I loved, but it was all to easy to completely shaft my setup and not be able to roll back.

vasergen

> Unless something _just works_, you're looking at hours of debugging which will most likely lead to failure.

Exactly my experience, in this case I simply switch to my OS package system (I use Nix only as a package manager on my Ubuntu). I think, I have round 95% of software coming from Nix, for the other 5% that doesn't work out of box, I just do 'apt-get install'

Also, for installing different programing languages I switched from Nix packages to 'asdf', because packages on Nix often not up to date if I want to try recent release.

ashtonkem

I think they were using NixOS, not just Nix, which means that you can't fall back to the "OS package system" because Nix is the OS package system.

The difference between Nix and NixOS was a branding mistake by the Nix team. It's unnecessarily confusing.

marcus_holmes

I just switched away from asdf (primarily developing Go on Mac) because of the problems it caused.

codethief

What problems, if I may ask?

nine_k

I'd say that packaging an app for NixOS should include rewriting all such impure steps, and making the fonts packaged along with the app is one such step.

If the fonts can't be packaged for licensing reasons, even as a separate package, then well, you indeed can guarantee that you'd be able to install the app next time. If it's not what you seriously need, then likely the value proposition of Nix is not for you.

colinramsay

I agree. That doesn't negate the fact that it took me a while to understand what the issue was, see if I could get around it, work out how to disable the font downloading in Flutter, etc, etc. I may have been trying to force a round peg into a square hole but NixOS didn't do much to help me see the shape of the pegs and holes in the first place.

CyberShadow

> Previously I used Arch, which I loved, but it was all to easy to completely shaft my setup and not be able to roll back.

Here is my attempt at solving this problem: https://github.com/CyberShadow/aconfmgr

Ambroisie

I remember reading about your project a previous time NixOS had been mentioned on HN, and tried to look for it again but couldn't manage to bring up the correct set of keywords to find it.

Thank you for posting it again. I don't think I'll go back to Arch unless I grow tired of NixOS, but if I do I'll be sure to give it a spin!

colinramsay

I'm going to look into this, thank you.

colordrops

This was a dumb choice by the flutter team. Yes, Nix doesn't provide an easy workaround, but let's not put all the blame on Nix.

JamesSwift

Nix 'flakes' aim to address your first issue by requiring all inputs be explicitly defined (including nixpackage itself).

patrec

I think the author is quite wrong that the nix language is not very good and hard to learn. In fact it's not only the best external DSL I've seen, but also one of the few cases where inventing a new language rather than just repurposing a subset of something already established looks like a good decision to me. In fact, I consider it a marvel of language design. The mix of properties that nix has (laziness, purity, relative simplicity and good syntax for things like path-names, records or interpolation) absolutely makes sense for the problem domain and would be difficult to achieve with something more off-the-shelf.

That is not to say there are no significant problems with it: the lack of static typing coupled with low runtime performance and bad error messages and debugging support means tracking down more complicated errors can be a pain and the laziness can further compound this.

The main big design flaw in nix (as an ecosystem), from my perspective, is that there isn't enough separation between the parts of the build specification that a purely data driven (git hashes, version numbers, license info etc) and the parts that actually need computation (specifying a complex build recipe conditioned on various things). This lack of separation makes it harder than it should be to have tooling to programmatically transform the pure data bit (e.g. to bump the version) and also really raises the barrier of entry. Stuff that should just require a newbie to tweak some toml file often requires messing around with nix instead. There is tooling that has this separation (niv, for example) but there are a bunch of different solutions following different conventions and nixpkgs itself happily jumbles metadata with actual code. I think this has significantly held back the ecosystem. Specifically 99% of users ought to be able to just tweak some toml files to satisfy their needs rather than learning nix. This is starting to improve a bit with stuff like toml files for flake, but it's still not great. I also think the ergonomics of many of the nix command line tools are rather poor.

But none of these issues seems to require significant changes to the core nix language (probably even the lack of static typing). So whilst I think there are significant practical warts, the core design is IMO extremely good.

flurie

I wish nix would implement the stdlib next to the language, even if it's written in nix and not C++. I hate that so many of the basic building blocks are hidden behind lib in nixpkgs. I feel like that accounts for a good bit of the barrier to learning the language. It's difficult to know the difference between a core language feature for the language's sake and a core language feature for the sake of nixpkgs.

patrec

Yes. I find the core language elegant, but I'm not equally enamored with the "batteries". I agree that this is a big barrier to learning how to do something useful with nix, I'd say much bigger than understanding the actual core language.

There are at least two problems: one is that, as several commenters have already mentioned, there is not enough consistency amongst different idioms for achieving certain results even within nixpkgs itself and sometimes both some deprecated and some new idiom are in use, which especially matters for stuff that is not trivial to start with (like overrideAttrs or overlays).

The other is that IMO even some of the conceptually simple stuff imposes too much mental overhead.

So instead of writing `if true then ["foo"] else []` (which is trivial to understand without any nix knowledge) the more idiomatic way is to do `lib.lists.optional true "foo"` and instead of `if true then ["foo" "bar"] else []` `lib.lists.optionals true ["foo" "bar"]` (which is completely obscure, unless you look it up).

I'm not sure such minor abstractions pull their weight for a special purpose language that most users should only spend very little time with.

I think what nix would really need to fulfill its potential is a multi-month top down pruning and rationalization effort from a person or team with a good eye for developer UX and not too much expert blindness to trim back many years of organic growth and provide a smoother learning curve. At the moment you need to learn far too many things at once to get anything done, whereas it ought to be much more pay-as-you-go: as long as you don't need to customize or create your own build recipes, you shouldn't have to touch nix code at all (and no, bumping a version doesn't count as long as there's no need to change the actual build steps).

No matter the benefits, I don't think Nix will grow beyond a narrow niche as long as any deployment of it requires anybody who comes in contact with it (i.e. not just the local nix guru) to devote significant mental resources to it. The typical (developer or sysadmin) end user needs something where simple stuff can be solved by editing a straightforward toml file (or similar) and running a cli command that requires as much (or less memorization) as typical uses of docker.

flurie

I find the language/ecosystem-specific idioms really interesting from a historical perspective. I feel like it makes for great reading if one wants to know the common problems involved in building packages for a given framework. I spent some time fixing some packages on Darwin for the most recent release, and I was surprised by how many of those were stdenv-based. I don't really write C/C++, so I don't end up using the stdenv builders myself.

At some point, one of my fixes used an "old" idiom; it was valid, but it had fallen out of use. It was just the first example I found for what I thought would fix the package, and it turned out to be correct, but the new idiom was cleaner and clearer. Nevertheless, they took my fix with the old idiom, so it will continue to propagate for what is likely the same reason. Some of this is just a result of the size and scope of the work going on, especially around release regression time.

In a separate personal example, I went down a very deep rabbit hole of trying to figure out why I couldn't use a shell as a base for a derivation that was essentially just packaged code used as a payload for an external system. It turns out that shell derivations are special things and can't be used directly for standard derivations. My eventual solution, using them indirectly, seemed hinky and didn't incrementally cache well, but it worked.

I agree very much with the problems you've described, but I am a bit more bullish on the potential of the larger ecosystem to outgrow at least some of those problems. I think flakes are the key to enabling better decoupling from nixpkgs. One could rewrite a saner stdlib as a flake, which could then get pulled back into nixpkgs as a flake input. There are promising tools like devshell and flox that are making a serious attempt at unlocking broader adoption through ease of use.

avakand

>That is not to say there are no significant problems with it: the lack of static typing coupled with low runtime performance and bad error messages and debugging support means tracking down more complicated errors can be a pain and the laziness can further compound this.

Some of this problems can be aleviated with good IDE support or language server.

Ericson2314

Yes, this is a very good take.

hypersoar

I've been using Nix for about a year. I don't use NixOS but home-manager and nix-darwin. Just about every single time I've tried to do something new, it has ended up being way more complicated than I thought at first.

- Installing emacs? You'll want to use the binary cache. No biggie. Except when it doesn't work, and your system update ends up building it from scratch--a two-hour process on my stalwart old desktop.

- Setting up a local environment for a Go project? No problem. Er, except some tools need to be installed globally, quite against the Nix philosophy.

- For a system or home configuration, you'll encounter packages, modules, and flakes. Packages are explained in the Nix documentation. The functions people actually use to make packages are explained in the Nixpkgs documentation. Modules are explained in the NixOS documentation. And flakes are explained in...uh...well, you'll figure it out. (You don't need flakes at this point, but they're on their way. And they won't replace packages entirely.)

- Debugging? gl,hf

- And this is all before we get into my admittedly complex system configuration using flakes, nix-darwin, and home-manager. Some things need to be set up at the system level, others at the home level. And cross-referencing the two is a pain. I just got an M1 mac. Some packages need to have their x86 versions installed, against Nix's protestations. I appreciate the guy who made a configuration framework that figured out how to do this, because I certainly couldn't.

Anyway, I love it.

I think it's the mathematician in me. The whole idea is too aesthetically pleasing for me to resist. The hope of having everything placed just so by a mere wave of my hand, too tempting. Damn the consequences.

dqv

>Installing emacs? You'll want to use the binary cache. No biggie. Except when it doesn't work, and your system update ends up building it from scratch--a two-hour process on my stalwart old desktop.

Just don’t use emacs ;)

In all seriousness, were you pulling from unstable? Disallowing installation because the hydra build is failing has gotten me, albeit for an obscure package I never use.

>And flakes are explained in...uh...well, you'll figure it out.

This is a funny quirk in the community I’ve seen, where everyone talks about using flakes but has a very difficult time of saying how. I finally figured out the weird incantation to get flakes to work. It was not trivial. (And the reason I’m not saying it here is because I simply don’t remember.)

AceJohnny2

> I finally figured out the weird incantation to get flakes to work. It was not trivial.

Care to share with the class? ;)

pimeys

For the system, I like the devos template:

https://github.com/divnix/devos

The idea of flakes is how you define inputs, and you define the system (and packages, and shell etc.) in the outputs using the inputs. The inputs are git repos which point to other flakes. You can mix and match these as much as you want (see the devos repo for examples) and when you build the derivation, it generates a lockfile for exact commits in that point in time what were used in the given inputs.

You commit the lockfile and in the other systems where you pull your config from the repo, it uses exactly those commits and installs the same versions as you did in your other systems.

This was quite annoying and hard to do before flakes. Now it's easy.

The problem what people face with building their system as a flake is combining the packages so you can point to `jq` from the unstable nixos and firefox from the stable train. I think this aspect needs better documentation so it wouldn't be so damn hard to learn (believe me, I know). Luckily there are projects like devos that give a nice template for people to play with (with documentation!)

Another use for flakes is to create a development shell for your repo, an example what I did a while ago:

https://github.com/pimeys/nix-prisma-example

Either have `nix-direnv` installed, enter the directory and say `direnv allow`, or just `nix develop` and it will gather, compile and install the correct versions of packages to your shell. Updating the packages? Call `nix flake update` in the directory, commit the lockfile and everybody else gets the new versions to their shell.

42jd

I wrote a blog post on NixOS/home manager configurations with nix flakes. I make sure to link out to other resources for those who don’t have the whole background. See: https://jdisaacs.com/blog/nixos-config/

xyzzy_plugh

> Setting up a local environment for a Go project? No problem. Er, except some tools need to be installed globally, quite against the Nix philosophy.

I have yet to encounter an environment I can't fit into a nix she'll, what requires globally installed tools? Sounds like a bug.

gypsyharlot

I always found Guix more appealing, because it uses a programming language that is useful for other things as well (GNU Guile). I really can't stand having to learn a new language for each thing I want to manage.

mplanchard

I completely agree, but the main benefit nix has over guix is some amount of MacOS compatibility. I don’t currently use a Mac, but I know that next time I have to use one for work, my home-manager-mediated config, which contains almost all of my user-specific configuration, will port right over just fine. The guix team doesn’t seem particularly interested in supporting MacOS, and I can’t blame them.

The other benefit is mindshare, so things tend to get updated more quickly in nix than in guix.

I do really wish I could use guile rather than the nix language though. I’ve gotten used to it, but the complicated abstractions in nixpkgs are still often inscrutable.

ninjin

I have had NixOS as my daily driver for nearly three years now and maintain a small number of packages in Nixpkgs. From my perspective, macOS support is a headache as it all of the sudden may require you to debug on a proprietary OS that you lack access to and that runs on two different hardware architectures in order to get a patch accepted. I am probably not going to make any friends for saying so, but I would much prefer if Nixpkgs for macOS was maintained separately.

My personal reasons for not going with Guix is that it is a GNU project and thus you have to buy into the entire FSF philosophy. Sadly I do need to run on “problematic” hardware from time to time and would prefer if doing so did not require me to add unofficial extensions and be wary of uttering such heresy in the company of my fellow users. That being said, I like what Guix is doing and their documentation does frankly look better compared to the grass where I am standing.

Lastly, yes, NixOS is a damn curse. Once you get the taste of having a declarative operating system it is really hard to go back. Trying out tiny tweaks to your audio, kernel, etc. all with the confidence that you know how to get back to what you had before is so very addictive. We need more diversity in this space.

rekado

> My personal reasons for not going with Guix is that it is a GNU project

That's a high price to pay.

Look, the GNU project means different things to different people.

On of the goals of the GNU project is to give users the tools to liberate themselves from arbitrary restrictions. The Hurd pretty much does away with the concept of an all-powerful root user as the only privileged account to alter settings such as network, file system virtualization, drivers, etc.

Emacs is designed to be a collection of extensions; the Emacs paper makes it a point to show that Emacs brings programming to people who aren't traditionally seen (nor see themselves) as programmers.

Guile was designed to be the extension language for every part of the GNU system that was still constrained by the dead systems programming language C.

Likewise, Guix aims to give “end users” control over their software environments and systems, privileges that used to be reserved for the sysadmin class. All design decisions in Guix are aimed at extending privileges to users: package transformations, package inheritance, building packages from JSON descriptions for those averse to Scheme, per-user channels, time machine, an extensive API to build and export systems, virtual machines, containers, environments, etc.

That's what I feel the GNU project stands for, and that's why I work on it and claim the name despite the PR problems that some GNU contributors keep producing.

> you have to buy into the entire FSF philosophy

Hell no! I don't donate to the FSF, I'm not affiliated with the FSF. The FSF has no say on what happens with Guix (and when I was co-maintainer and rms tried to tell us to remove clang from the package collection we told him we disagree and that was that). Guix abides by the Free System Distribution Guidelines, which were published by the FSF. This means that Guix does not come with proprietary software by default.

Guix makes it trivial to add the nonguix repo (or any other repo for that matter): just add it to your channels and run `guix pull`. Now you've got the vanilla kernel and firmware packages and whatnot. You can chat about it all you like on #nonguix. We just ask to keep discussions of proprietary software out of the main channels. Doing that anyway is not "heresy" (I'm sick and tired of the religious vocabulary being applied to people who work on replacing proprietary software with free software) but just ... rude, I guess.

So, I welcome you to sample that greener grass up close. It might pale a little when you're debugging, but at least you get to use Scheme.

mplanchard

Oh yeah no doubt MacOS is a huge pain. We use nix for installing system deps at work, and it seems like once every six months or so something will inexplicably stop working on Mac. Luckily I have an old Mac at home, but the new architecture means that one is becoming pretty much useless now for debugging some of the stuff that comes up.

Still, being able to guarantee everyone working on the project has the same versions of everything is pretty nice. No need to worry about ancient Mac versions of bash or awk or sed or whatever, so we can script confidently.

xyzzy_plugh

In the long run macOS support will prove valuable for shaking out a ton of cross-platform build issues. I see the macOS support as a huge, compelling and underfunded reason to try nix. The fact that I can avoid homebrew entirely is incredible.

It helps me and my peers flex our Nix muscle regularly, which means when we have to do real Nix work it's fresh in out minds.

Sure, there are rough edges and baggage and purism pain but I wouldn't trade it for anything else.

Frankly I think nix-darwin should be rolled into nixOS.

globular-toast

Is the author aware of Guix?

alpaca128

Apparently not, or forgot about it when writing the article:

> it's so clearly the only operating system that actually gets how package management should be done

Filligree

He might be one of the many, many people whose hardware isn't supported by Guix.

xxpor

Isn't Guix just nix with guile?

valyagolev

as much respect as I have for Guile, I'd love the nix configuration language to have at least partially enforced types...

eadmund

It really is a pity that Guix didn't go for Common Lisp instead — it does allow for gradual typing. And it has standardised a ton of stuff that Guile had to implement on an ad hoc basis.

dannyobrien

Honestly, I kind of like how Guix and Guile have been growing together. Like Rust and Servo (and the Rust compiler), I think the constraint of having a general-purpose language, but a general purpose language that is also responsive to a bigger project, has been beneficial to both.

agumonkey

time for hix .. and lets revive http://lambda-the-ultimate.org/node/299

yaysyu

Does guix also have any equivalent to patchelf?

georgyo

Guix uses patchelf.

Patchelf is very useful anytime you want to change the location of dynamic loaded libraries but don't want to set LD_LIBRARY_PATH.

It is used in more places than you might originally think.

rekado

We don't use patchelf for any official package definition. We have a package for patchelf, but it's only really useful when you have pre-built binaries that you can't rebuild from source.

lillecarl

GoboLinux also uses patchelf.

seddona

Interesting to see exponential growth in NixOS github stars https://star-history.com/#NixOS/nixpkgs&Date . Perhaps the user base is reaching a tipping point where there will be the resources to address some of these problems.

floatingatoll

What fraction of those who starred a project on GitHub become committers to and/or donate more than once to it?

I've always assumed that this is a vanishingly small amount, on the order of one in ten thousand or so, but I could be underestimating.

jonringer117

Currently, there's 8.7k stars, 7.2k forks. And 2000+ maintainers have added themselves: https://repology.org/repository/nix_unstable

So, I would say a pretty large portion.

Also, the contribution model for nixpkgs is just opening a PR, so it's a fairly low (non-technical) barrier-to-entry for most contributors.

gushogg-blake

> but the connection between those two things is essentially undocumented

I often think documentation would be vastly improved if the author was simply answering the question _what problem did you solve, and how?_, but that seems like it would reveal too much of the dirty details of the design process somehow, so they try to describe the all the neatly encapsulated abstractions and metaphors they've come up with to describe the system (and to encode their own eventual understanding of it) instead. Basically - give us the dirty details and we can make the generalisations ourselves, instead of trying to load the generalised structures into our minds in the most efficient way possible.

tazjin

This implies that the author of the documentation is the person that wrote the thing though, which is surprisingly rare in larger projects.

I wrote one of the more popular Nix language tutorials[0] and my approach there has been to try and explain everything as straightforwardly as possible and make it work both as a reference and a manual (i.e. you can quickly jump to a section that interests you, or read it from top-to-bottom).

One thing that nixpkgs (the Nix package set, which is ~most of the public Nix code) suffers from is reinvention of abstractions (simply due to its age). For example, most programming languages have their own slightly different implementation of a `withPackages` function that gives you a prepared environment with some dependencies. Some of these use open sets, some of them use closed sets, in the latter cases overlaying things into them can get really confusing even for experienced Nix users and so on.

In my opinion, the community should slow its focus on making lots of new features and spend time consolidating existing logic and agreeing on some basic abstractions. Maintenance work like that is not always fun though, and especially in unpaid open-source projects it's difficult to keep up the motivation for it.

[0]: https://github.com/tazjin/nix-1p

Daily Digest email

Get the top HN stories in your inbox every day.

The Curse of NixOS - Hacker News