Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

ever use nix repl? i found my complaints about grokkability disappeared once i realized i could easily introspect my build (and all my dependencies' builds) at any level.

that + learning the like 5 or so idioms that pervade nixpkgs and you can use Nix quite successfully imo.



sort by: page size:

I use Nix for every project once it grows enough for me to have to pin a directory. And sometimes sooner.

I don't know it that well but I've picked up on design patterns, use the repl to figure stuff out, write small abstractions when necessary..and it works pretty great. And the gains grow as my dependencies become polyglot (even C + another language like Haskell..but when you add compile-to-JS, static asset generation into the mix it's amazing)

Yeah it's hard to learn. No denying it. But every other "alternative" I've found doesn't actually approach it. So I've kind of gotten sick of reading about "alternatives" because it always feels like they don't actually solve the problem Nix solves. I always end up using the alternative+Nix. Classic example of this is the Haskell stack build tool.

I could've bemoaned complexity and various capitalist criticisms when I first ran into it at a job. But I'm so much better off for not.


I totally get that sentiment about nix, and actually I sort of share a variation of it too: I really want to learn it, and I like the featureset in theory, but I can't get used to it in practice, and I don't have the time to invest myself into something that difficult to get going.

The reason I brought up the nix command is that I only use nix, for haskell development, for that specific command: I found it once in a blog post, saved it, then put it under a function into my bashrc, and I use nix quite literally for only that purpose. I've done a lot of development on various functional languages (with a dayjob in F# that lasted 3 years) and being able to quickly experiment with libraries was something that I sorely missed when doing repl experimentation in those languages (I think F# recently got a #nuget directive, but that was after I stopped using it).


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.


Nix the language enables you to write explicit build recipes that can be reproducibly built with good integrity guarantees and granular and distinct knowledge of the build-time dependencies and the run-time dependencies (so you only ever transmit closures that have what they need to execute).

Nix the set of tools gives you convenient command line tools that can: evaluate Nix language expressions, build recipes, analyze build-time or run-time dependency graphs of a recipe, give you ephemeral shells with the packages you want in scope but not installed "globally", package management tools to install packages globally, and recipe diffing tools so you can see how recipes changed.

Nix the package manager is a convenient, gigantic, community effort to explicitly describe how to (reproducibly) build almost all of the OSS software that users need and it comes with a substitution cache so that most recipe build products are easily substituted when installing, so you don't have to build. Even if you don't use Nix, nixpkgs is still impressive because you have the most explicit documentation for how to build a piece of software from source and all of its dependencies than anywhere else on the internet, it usually rivals project author's in its specificity, explicitness, and clarity.

NixOS the Linux distribution combines all of this together with a convenient configuration module system and generally good defaults to give you an operating system that is declaratively specified from your etc hosts file all the way down to the recipe for building the kernel, a rich and granular dependency graph, reproducible OS configuration builds, and diffs between closures.

My biggest gripe with Nix is the lack of static types. This was the originator's biggest mistake that Nix will be living with for a very long time to come. Static types would have helped bring the learning curve down IMHO and made it easier to document and less frustrating to debug.

That being said, the overall properties of Nix, nixpkgs, and NixOS far outweigh the pain points in my six years of production experience with it and for what we care about: auditability, reproducibility, explicitness, efficiency, and integrity.


I have a very minimal nix.configuration, write very small shell.nix files, and try to only use things I know or understand. So I’m definitely only using 1% of Nix right now but I’m comfortable with it!

Edit: I should clarify Nix is the build tool at work for Haskell and some of my colleagues are contributors so I know I can get help if stuck. I’m a noob though.


Thank you for the explanation. I'm going to go back through everything I've read and see where it helps me.

However, I just want to address one thing.

> To be honest, nix is a system you have to actually use to begin to understand and synthesize. As noted, flakes make this hill less steep, but you won't really internalize the value and the system as a whole until you actually start using it some.

This is discouraging me from trying Nix for a couple of reasons.

Having read the thesis, understanding the necessity of reproducible builds and how Nix turns that up to 1100, and looking forward to being able to tell future contributors of my software to just run `nix-shell <whatever>` to set up my exact development environment, I think I understand the value of Nix pretty well. Being told that I don't understand it's value just because I don't use it feels a bit like condescension or elitism. You probably intended none of that, but that's what it felt like.

Second, flakes have not made the hill less steep for me; they've made it more steep, simply because understanding wasn't there. Some things are harder for some people than others, including things that seem like they should be easy to anybody. Math is easy for Terence Tao in a way that it's not for me. But I bet you there is something I'm a natural at that he finds hard or impossible.

Third, I agree, after all my study, that Nix is easier to understand once you use it. My trouble is that a package manager is a critical part of my system, and I don't want to run it until I do understand it. Standard package managers may be bad compared to Nix, no doubt about it, but they are understandable, which means I've been able to fix them when things go wrong. I have no such confidence that I could do that with Nix, so I haven't used it yet.

It is unfortunate, but there are a myriad of reasons why people who know about Nix, and want to use it, haven't yet used it. Sometimes, the reason isn't because they don't understand the value of it. I don't like that I am not yet confident enough to use it, but that's my situation.


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.


I started on my Nix journey a few months ago, and in some ways, I've had the worst-possible experience— I had basically no ramp-in period of being just a "Nix user" before attempting to write my first package, but was instead thrust immediately into a massive project templating out generated definitions for 1000+ interlinked packages with a bunch of oddball requirements, funky build tools, etc. I've needed to manage version and patch overrides, obscure linker conflicts, stuff that broke at runtime due to unpropagated buildInputs. I'm also a functional programming novice, so that recursive combinator magic which makes the overlay system work— also something completely new that I've had to wrap my head around.

So yes, all this has been... somewhat harrowing. But overall I would say I'm quite pleased with the end result and impressed with what Nix has enabled. Despite its long evolutionary growth, many of the things that I've encountered feel thoughtfully considered and well made. The various ways that builds and binaries can be pushed around and shared is awesome, and I'm excited for the optimizations coming with the content-addressed store.

I don't think that making the Nix language or package definitions feel more conventional would necessarily be a good thing— I think there's a risk that those kinds of changes obscure the underlying realities and lead to expectation mismatches.

That said, one thing that I do feel is pretty unfortunate is the interplay between the shell and Nix in package definitions. Basically you pass a dict to mkDerivation, and all the stringy items in that dict become available to your build's environment as envvars. This means when writing out strings for your configurePhase, buildPhase, etc, you have to be hyper-aware that ${thing} will be templated by Nix in the Nix context, whereas $thing will be templated much later, by Bash. It's something that is learned quickly but my goodness is it ever a hell of a tripwire.


The language is not the hard thing, it's actually straightforward once you get it. It's the crazy amount of convention and the number of layers in the stack that make up the Nix ecosystem that takes so long to grok.

People complain about learning 'the language' when the thing they've really been trying to learn is actually:

  - the language
  - the stdlib (nixpkgs.lib)
  - the NixOS module system
  - several particular packaging ecosystems (stdenv, buildGoModule, buildPythonApplication, etc.)
  - the hooks and stuff that get exposed as variables and functions in bash-based builders
all at once! (plus maybe even the derivation format)

It makes sense as a shorthand, and I'm sure it describes the feeling, that people say 'learning the Nix language was overwhelming at first', because using the language in the context of all of those other things (essentially libraries and applications written in Nix) is the context in which one generally tries to learn it. And that really can be a lot to take in at once.

But I think when someone says 'learning the Nix language was hard' or something similar, it does sometimes mislead others about the complexity of the Nix language itself. So there's this widespread misconception that Nix-the-language has a lot to it.

But like you say, the language itself is actually super minimal. (And really good for its intended purpose, imo.)


Actually, the thing we started using nix for was reliable caching of compiled artifacts, including not just your code, but all the programs and libraries that your code depends on. It's another thing that's difficult to do in a general sense, but if you have a fairly strong notion of reproducible builds, it's possible.

I’ve looked into Nix at the previous company I worked for for exactly those reasons. I spent a bunch of time writing minimal dependency builders and artifact reuse for a maven monorepo where I had to tread carefully and not break the build. Nix seemed like a great way to get inter-repo dependent builds and dependency modeling.

Disagree. The larger selling point is Nix reproducible builds. Getting a reproducible developer environment is a start, but everything inside that “shell” is then mutable. Hiding Nix behind YAML is obscuring a tool, Nix, to make the entire build stateless—and that YAML can often be a stopping point where folks aren’t going ‘deeper’ to unlock the reproducible build part.

There are things it does that are very helpful, like enabling a PostgreSQL server without much setup, but other things like forcing certain language toolsets goes a bit too far—especially when those tools are already in Nixpkgs and setting up a base devShell provisioned with a few console tools is one of the easiest things to do with Nix the language already.


Oh, nix is an extra mile. A lot could be improved, but that's what I'm using to deal with dependencies.

Does Nix still have that extremely steep and high learning curve and huge time invest before you actually grok it? I'd love a Nix that is about as hard to use as homebrew, but no luck so far.

That sounds great. I remeber when I started, it was very difficult, I don't think I would be able to start without nix-pills articles.

Nix needs more tutorials, especially in areas that could showcase it (which you planning to do).

Nix is often referred as a package manager, but I believe that characterization does a bit of disservice to it, because it can do much more than that. IMO the areas where it excels the most for me is the build system. Ability to have a language define the exact environment that developer has is IMO awesome.


It is great, but a bit painful to learn and get working for you. I like to use Nix to provide my development environments but that's often painful due to conflicts between the Nix approach and how the language package manager wants to work.

Yeah, It's really amazing that so much of it is not hard coded features but just idioms in nixpkgs. But that might make it harder to learn.

|nix keywords| << |docker keywords| << |nix idioms|


Nix has a heavy learning curve and requires learning the language to feel comfortable. However, overcoming that hump is incredibly rewarding and allows for taming your system in a way that, for me at least, changed the way I look at composing software.

At mindbuffer[1] we've started using it for our recent art installations. The big benefits for us are reproducibility, ease of deployment, and the ability to collaborate on the composition of the whole system. I.e. rather than sharing a README of how to install things one by one and hoping each of us has followed it correctly, we just work on the same set of config files via a git repo (like we would any other code) and can be sure we're all on the same page as a result.

Very much looking forward to Nix 3.0 landing with all its UI improvements and flake support. It seems like these changes will go a long way to making Nix more accessible, and provide a smoother on-ramp to learning the language itself.

https://mindbuffer.net/

next

Legal | privacy