Live data from Hacker News

My First Impressions of Nix

mtlynch.io

311–320 of 354 posts

Re: My First Impressions of Nix

#311

Seeing a tweet like the one from Mitchell makes me want to try Nix. Or at least I want to want to try Nix. Then I read the comments here and am reminded that no one can even succinctly explain what Nix is. I've read dozens of comments here and I still don't have a clear idea!

I suspect you may take other technology you use as granted, and have forgotten the inherent subtlety that you've had to work through to attain the working understanding you have today. Consider the confusion you might have being an aspiring developer, on your first day cracking open a book on $INSERT_LANG_HERE, and then someone mentions Docker. Imagine your confusion:

"What is docker? It builds things? So, like, a "build system"? But it invokes something called make, or cmake, or... well, aren't those build systems? If that isn't confusing, I don't know what is. Oh, you say it's software that runs on Linux -- what's that? So docker is an OS? No? It runs on an OS? And you're telling me it doesn't just build stuff, it also can coordinate the execution of stuff? Oh, you're telling me that's docker-compose -- that isn't docker itself? I mean, it had 'docker' in the name. Oh. So separate project to 'docker the container image making thingy', but can be used with that 'docker'. Good God this is confusing."

Much like the Docker and its ecosystem as whole -- along with all the enabling/leveraged tech underlying it, like chroots, user/pid/network/etc namespaces, union filesystems, seccomp, etc -- there is some inherent complexity in Nix (and its broader ecosystem of tools).

Just like docker has docker, docker-compose, docker images, stateful docker containers (is it running? dead? what subtree of my filesystem is mounted where in the container? etc), a whole syntax for "docker files", etc, we have multiple things that come together to make "the whole of Nix" what it is.

As a whole, for Nix we have (non-exhaustive, but hopefully broad enough to help paint a picture):

- Nix the language (analogous to Dockerfile syntax), which is used by

- Nix the package builder/manager (analogous to the `docker` binary)

- Nixpkgs, which is a collection of packages (a bit of a stretch if you take it too literally, but analogous to a collection of Dockerfiles, each for a different software)

- NixOS, an operating system that leverages the packages declared in Nixpkgs.

That hopefully explains the "WHAT", but says nothing of "WHY".

So to touch on the "WHY" a bit:

- Dockerfiles are not reproducible. What builds today may fail tomorrow, or next month, or on odd numbered days, or whatever.

- Nix packages are reproducible. If it builds today, it will build on any machine, any time. Guaranteed.

- On distributions like Debian/Ubuntu/etc (essentially anything that isn't NixOS or inspired thereby, like Guix), when you install a package, and something goes wrong, your system can end up in an in-determinant state that requires human intervention to manually sort out how to unbreak things. Just google (or just recall the last time it's happened to you -- and if it hasn't happened to you, it eventually will) people desperately asking for help to unbreak their system after, say, Ubuntu's apt (or whatever) gets screwy and says it can't install/uninstall anything else because $INSERT_CRYPTIC_APT_BUZZWORDS_HERE. Oh, and add to that the compounding effects of the fact that any package can include raw bash commands as post-(un)install steps -- that's just asking for packages to fail to (un)install cleanly depending on what else the user does/doesn't have installed at that point in time.

- On NixOS (and similar) the system state is guaranteed to either update fully or not at all -- as a consequence of its design, none of the chaos mentioned can happen. It's not that it's unlikely. I literally mean it simply can't happen. System updates are guaranteed all or nothing. Also, if you find out that some configuration change isn't what you wanted, you can roll back in instant (that's not hyperbole -- rolling back entails no slow error prone file copying/writing/etc, literally just one symlink change, and "poof" you're on the previous version).

In a nutshell, from top to bottom of the stack, the selling point is: imagine a world where "oops -- that failed in production, but... well, it worked on my machine, I promise!" simply can't happen. Imagine the time savings, and the reduction in anxiety if you knew that, if you could successfully build and/or deploy a particular piece of software once locally/in-staging/etc, you have full confidence that you can repeat that on any machine at any time.

Admittedly, if you enjoy those struggles with conventional non-Nix(OS) setups, there isn't much value to Nix.

Re: My First Impressions of Nix

#312

Earlier quoted context omitted.

I'm not sure. Well, I mean, there are weird folks out there who may start doing large-scale things without understanding what they're building upon (Kubernetes is not exactly an OS, but is a notorious example), but they could make the same mess with any technology. They're just unlikely to pick Nix, NixOS or NixOps (or any alternative to it), because mainstream tutorials won't cover it [yet]. The deployment and learn…

well, an anecdote for an anecdote: reading the definitions of nixos modules became a matter of course for me when i started doing strange stuff that didn't quite fit into the authors' expectations, and those module definitions contain the implementation, i.e. exactly where files are placed and what's written to them. i learned things about how a distro is put together that i never had any reason to look into in the p…

Ah, my apologies, I think I've misunderstood you. Yes, absolutely, I agree - reading definitions of those modules is how one learns Nix. Documentation is okay, but it doesn't cover neither the essential theory like patterns, practices and idiomatic approaches, neither implementation specifics (how some particular config file or startup helper script is generated).

Although, to be fair - reading source code of how things work is not really specific to Nix. It's just that Nix doesn't stop at packaging and also provides declarative configuration, so there's much more to read in nixpkgs than inside some .deb source (which typically stops at providing a generic systemd unit or rc script). But if someone would be using some other declarative configuration tooling - I'm sure they'll also do a lot of deep diving into the definitions, reading the source code. It's just that Nix is outstanding in this regard - I suppose I can, but I surely wouldn't want to use Terraform, Chef or Ansible for what it does.

Re: My First Impressions of Nix

#313
post #69

Earlier quoted context omitted.

Memoization is state. As a functional programming maximalist myself, I know it hurts a little bit, but still, Caching/Memoization is statefulness. That said, you are right that as a user of the system, that statefulness is abstracted from you and you don't have to worry about it (until some subtle caching bugs forces you to dive deep in the rabbit hole)

Yeah I really bumped on this. A cache is absolutely state. It is sufficient to say "a referentially transparent cache is a technique to store state while avoiding most of the drawbacks typical to storing state". This is already a big accomplishment! No need to also redefine the word "state" to make the technique seem even more magical than it is.

It's state at a different level than most configuration management software deals with. When Puppet reasons about the state of an existing system, it asks things like 'what's on the PATH right now?'. NixOS doesn't— it reconstructs the directory tree under /run/current-system/sw/bin without asking that. Same with 'modification' of files that live under /etc. What you and the GP write here is nuance worth admitting, but I wanted to highlight what people are getting at when they say Nix's approach is 'stateless'. What they mean is that Nix's approach to state is really qualitatively different, and hands state off to be managed by a lower level part of the system as much as possible.

Re: My First Impressions of Nix

#314

Seeing a tweet like the one from Mitchell makes me want to try Nix. Or at least I want to want to try Nix. Then I read the comments here and am reminded that no one can even succinctly explain what Nix is. I've read dozens of comments here and I still don't have a clear idea!

I suspect you may take other technology you use as granted, and have forgotten the inherent subtlety that you've had to work through to attain the working understanding you have today. Consider the confusion you might have being an aspiring developer, on your first day cracking open a book on $INSERT_LANG_HERE, and then someone mentions Docker. Imagine your confusion: "What is docker? It builds things? So, like, a "b…

And as a pointed amendment here, here's a non-Nix experience I've had, which everyone eventually has:

My team discovers a major issue in a recent release. Conceptually, we need to rollback and we need to do so fast. However, we can't just deploy the same package/docker-image/whatever from the last release (perhaps because of a change in database schema, or whatever) -- we need the previous version plus some minor patches.

So I check out that previous version from source control.

I do `docker build`, and see a screen full of errors.

Huh. That worked when this ran in CI a week or two ago.

Oh, due to some petty political issues the devs of some third-party library (that is deep within our tree of transitive dependencies) have decided to nuke every posted version to pypi/rubygems/whatever and deleted the repo from GitHub.

Yaaaay. Okay. Fuck.

Would have been nice if we had a local cache/mirror of that, but there's nothing about docker that guarantees you'll have a copy like that (Nix does provide this).

Gotta push through the panic and weight options:

Do we try to replace every dependency that uses this lib?

Holy smokes that (transitively) touches a ton of our code base. Not impossible to do, but almost impossible to consider what the ETA will be for that, and remember that we're trying to put out an active fire here.

So... we could see if anyone online has a fork of the repo...

But then how do we know it hasn't been tampered with? It's not like pip/npm/rubygems has some content-based hash we can use to assert that this library's source tree is as expected, and it's not like Docker tracks/asserts such a content-based hash (Nix does track this).

Cue an hour or two of immense stress and customers being very unhappy. Oh, and there's nothing to say that this won't happen again -- after all, docker does nothing to help with and/or enforce determinism/reproducibility of builds. I mean, it does guarantee runtime reproducibility in that multiple machines can be running precisely the same image, but docker does not guarantee that you can reproduce the build of a given Dockerfile. These two different types of reproducibility should not be conflated.

Nix is specifically designed to prevent these types of scenarios.

Re: My First Impressions of Nix

#315

Now that we have another Nix post, maybe someone can enlighten me about something I've been wondering about. I'm one of the maintainers of a popular django application. Someone made a nix package of the project, but we've now twice gotten invalid bug reports from people using the package because the package depends on "django_4" and whenever someone updates that nix package, the package for our project breaks. Of cou…

It seems like Nixpkgs aims to minimize the number of package versions in use at one time. Not just nix, most package managers do, it seems (i.e. you wouldn't expect to find different minor versions of Nginx in Debian, would you?) So by that same logic, there is only one version of Django 4. It is definitely possible with Nix to use the precise versions of what's in your requirements.txt, but I'm not sure if the Nixpk…

> It is definitely possible with Nix to use the precise versions of what's in your requirements.txt, but I'm not sure if the Nixpkgs maintainers would allow all that extra duplication upstream.

They do for end user applications, but not for Python libraries. The libraries in Nixpkgs are expected to be interoperable, which requires converging certain versions because otherwise transitive dependencies on varying library versions mean that libraries used together are subject to serious, mysterious bugs. But applications packaged in Nixpkgs can pull in an exact set of libraries of their own if that's what it takes for them to run reliably.

Re: My First Impressions of Nix

#316

Now that we have another Nix post, maybe someone can enlighten me about something I've been wondering about. I'm one of the maintainers of a popular django application. Someone made a nix package of the project, but we've now twice gotten invalid bug reports from people using the package because the package depends on "django_4" and whenever someone updates that nix package, the package for our project breaks. Of cou…

Are you opposed to filing a bug in Nixpkgs for your application? Alternatively, are you willing to point to your application or its package in Nixpkgs so that someone else can do so?

Re: My First Impressions of Nix

#317

Earlier quoted context omitted.

> Of course we, like all other python projects, don't support using other dependency versions then the ones in the requirements.txt file. That's really bad. You should always support reasonable version ranges. > when someone just uses a different minor version of django, stuff breaks That's why some people say that managing dependencies in Python is difficult and move to statically compiled languages.

> That's why some people say that managing dependencies in Python is difficult and move to statically compiled languages. Yes, completely agreeing with that.

It's not even really about static compilation. NixOS (and many Linux distros) include tons of dynamically linked C applications that just do a way, way better job of compatibility. Imagine if GNU grep were as fussy about only being built against 1 version of glibc as many Python libraries and applications seem to be about their dependencies.

Re: My First Impressions of Nix

#318
post #154

The problem the author hit with the Raspberry Pi is that the ARM image is meant for a standard environment (e.g UEFI ), like VMs. e.g it'll boot on Fusion or kvm because they provide UEFI, a well known device tree, and don't require any firmware at that stage. Pis (and many such ARM boards) don't have that so they won't be bootable. But there are Pi images built on Hydra. If one uses that then it boots right away. It…

This comes down to ideological reasons. The engineer that is/was leading the embedded integration subproject feels like the platform support components (filesystem partitioning, bootloader, devicetree config, etc.) of installing a distribution on the hardware should not be a concern of the distribution itself[1].

I don't necessarily agree on all points as most distributions approach this quite differently, but it's an interesting premise. There are other projects that attempt to attack this problem but I'm unsure if any have gained a critical mass.

[1] https://discourse.nixos.org/t/planning-for-a-better-nixos-on...

Re: My First Impressions of Nix

#319
post #276

Earlier quoted context omitted.

I've never had to do much for Nix itself, but packaging something to build from source can often require quite some effort. Applications that use a pretty unconstrained build/install process upstream may expect to do a lot of things that are not allowed in the Nix build sandbox, like unconstrained network access and or overwriting files in existing packages on the system. To deal with that you really have to dive in,…

You can mitigate this to some extent by approaching it as described here: https://www.haskellforall.com/2022/08/incrementally-package-... I think Graham Christensen had a blog post along these lines... I'll see if I can find it. Edit: I couldn't find it... but I thought someone made a blog post about gradual adoption of Nix into a codebase.

Idk about a blog post, but he did a talk along those lines at the most recent NixCon: https://youtube.com/watch?v=asc1D5yPZhQ&

I'm taking that approach with the package I've been working on, which has a somewhat pathological (by Nix standards) Gradle build which does things like

  - manually download a copy of Elastic search outside of the normal Java dependencies scheme
  - run NPM to fetch remote libraries to build web assets at build time
  - *also* run Yarn, for some reason
  - use Git at build time
The ways it does all of these things are actually fairly thoughtful (for example, it does checksum the artifacts it manually grabs at build time to verify their contents), but they don't play nice with running builds in offline mode or under a user that has no $HOME. But it's one of those freeform 'my build tool configuration is a weird DSL in an imperative, general purpose, Turing-complete language' situations, and I'm not very familiar with either the language (Groovy) or the DSL. So it's a lot of quirks to cope with.

I've made quite a bit of progress in building it from source by making a few small patches and eventually disabling the sandbox for now, but it's still dying on a weird test failure for reasons I don't yet understand. At this point I'm just back to munging the binaries provided by upstream because I was mostly building from source to learn about the project and how it's distributed/deployed anyway.

I messed a bit with gradle2nix for a better-behaved, old school FOD-based build with Gradle in offline mode, but that was pretty brittle as gradle2nix is unmaintained, and due to some design limitations it couldn't actually capture all dependencies. I'm kinda interested in working out something better but on the other hand, this is a third-party package and I don't myself use Gradle or Groovy for any kind of development, so mastering Gradle's quirks and wrangling it into the Nix sandbox for this package is more of a yak shave than a practical skills investment for me.

Re: My First Impressions of Nix

#320

Seeing a tweet like the one from Mitchell makes me want to try Nix. Or at least I want to want to try Nix. Then I read the comments here and am reminded that no one can even succinctly explain what Nix is. I've read dozens of comments here and I still don't have a clear idea!

I suspect you may take other technology you use as granted, and have forgotten the inherent subtlety that you've had to work through to attain the working understanding you have today. Consider the confusion you might have being an aspiring developer, on your first day cracking open a book on $INSERT_LANG_HERE, and then someone mentions Docker. Imagine your confusion: "What is docker? It builds things? So, like, a "b…

Thanks, appreciate the thorough reply. This is very helpful. I need to think through this some more, but your example in the follow-up (where some dependency gets nuked) help concretize this. If I can get even greater reproducibility than Docker and it's faster, that's hugely appealing to me.
Post reply on HN