Yes, but that's not a problem. In traditional systems the reason to avoid rebuilding everything isn't because it takes time (it does, but not that much time); the reason to avoid rebuilding everything is the fear that, halfway through rebuilding everything, you'll discover that some shared lib is missing, or some crucial toolchain has been uninstalled, or that some updated packages rely on incompatible versions of the same dependency, and it turns into a nightmare of toolchain and dependency resolution, leaving your system in a half-upgraded mess. But if the promise of Nix is true, then that's no longer possible; you rebuild everything, all the dependencies work out fine, and you go on with your day.
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.
> the build and configure steps may change over time. Unless the original maintainers start building for nix, would not this be too hard to maintain?
This is indeed very hard, but Nix's deep locking makes this a tractable problem: if a version of a package builds once, it will keep building for as long as the source code is available.
So in some ways, this Nix has an easier job compared to traditional distribution mechanisms. On the other hand, Nix can be sufficiently weird and unwieldy as to limit the number of potential contributors.
If you are building a complex system with a large number of cascading dependencies then nix can literally save your sanity, however you have to get over the initial steep learning curve.
If your work tends to be more isolated and self contained on stable unchanging mainline or mainstream versions of any dependencies you have. Then it’s not worth your time and you won’t appreciate or understand it’s value.
This seems like a bummer. I'm under the impression that one of the points of nix is to have pain free rebuilds. I wonder how to address this issue and what the source is -- is it a critical mass thing (more users/contributors solving problems)? or an issue arising from inexperienced module maintainers?
It is, perhaps they didn't use cache to store previously built packages and build everything from scratch. With no cache Nix will start with building compilers and glibc until it has everything to build the actual application.
It's not the functional nature of Nix that is hard to deal with. Nix's functional nature is actually its saving grace.
My difficulty with Nix is that there are important subjects that aren't taught.
I figured out how to create a usable `default.nix` and `shell.nix`, but that takes a lot of effort, and there really aren't many resources to reference.
Nix expressions use a lot of predefined functions, and I have no idea where their documentation exists, if it does at all.
Even if there is some explanation for all of the functions that I need to use, there isn't documentation for how to fit them together.
Instead of being in dependency hell on the outset (like most package managers), I find myself in dependency hell when I want to do something different. The Nix community has an irrational hatred of version numbers, meaning you have to scour the web for a derivation that gets the right version of a dependency, and "pin" it, or hope that the channel you are using has the correct version. Even when channels do have the version you want, sometimes that channel provides multiple package versions, some with the version in the name.
Names are a mess. Since every package must exist in the same namespace, but its derivation is helpfully sorted into a directory tree, the same packages will often have different names. There isn't a good way to search or browse for them either. I end up digging through github quite often, which is a lot more often than the never that I should find myself doing so.
Nix is wonderful. NixOS is by far my favorite OS, and that is why I deal with all of the rough edges, but they certainly are rough.
Absolutely. I'm about a year deep on nix / NixOS and still spend way too much time refactoring things to be more DRY or what I think might be more idiomatic or maintainable going forward (as opposed to a more obvious but uglier approach). Definitely makes it easy to waste time prematurely optimizing, if you're prone to that sort of thing.
It sounds like your issues with Nix stem from its steep adoption curve, rather than any technical concern. This _is_ a concern for a team that needs to manage it - I agree.
I'm quite diehard in terms of personal Nix/NixOS use, but I hesitate to recommend to colleagues as a solution because the learning curve would likely reduce productivity for quite some time.
That said - I do think that deterministic, declarative package/dependency management is the proper future, especially when it comes to runtime environments.
Nix is not (yet) suitable for fine-grained (read file level) build targets though due to lack of recursive nix and content addressed store. This means you don't have early cut off and mass rebuilds if only one file changes; for example. Both are being worked on actively though.
I like the idea of Nix. It's definitely the future of package management and build systems. But it's solving a problem we knew how to solve in the 80s: dependency hell is solved by statically linking everything. In fact in the Windows world it's still like this. If you need OpenSSL, for example, it should be in your source tree and compiled in the same build pipeline as your application.
Yes, and Nix can still lose on maintainability in the long run, considering it is more difficult to onboard new devs with it. They have to learn the Nix expression language and write custom bindings for much software instead of calling the native package manager inside Docker.
Yes, for what it's worth I don't mean to diminish your experience. Nix definitely requires pouring a lot of time to get to a working state, is very under-documented, has terrible error messages, will cause errors that don't exist elsewhere, and has no clear "best practice" guide on how to use it. Those are all super annoying pain-points and I do hope they'll get better over time.
At the end of the day, it's a bit of a balancing act. For me, the up-front work of getting a nix build up was definitely worth it, as it allowed my collaborators to get up to speed on complex projects with complex build systems quickly, and gave me a very simple way to reproduce old binaries when I need to bissect bugs. But it definitely took a huge up-front investment.
If all you're after is a way to pin your toolchains, I echo the recommendation of asdf made in a sibling comment. I use it on simpler projects where I just need to pin a language version (and let the language tooling pin the rest of the dependency tree - package.lock-style). It will often be enough, and is much easier to get started with! The only thing that won't pin will be system dependencies (like openssl and such), but that is often an acceptable tradeoff.
You can continue spending your time messing around with your system then. I learned nix in a short amount of time and it has supercharged my development workflows and reduced the overall complexity. I have too much stuff to get done to not use it.
Life is too short to spend hundreds or thousands of hours learning a tool to save you time. Nix might give you 'perfect' reproducible builds but does the time saved from this beat the time taken to learn it? I'm skeptical.
I can see the utility of using Nix for managing dependencies of software you're developing, because that can be horrific to deal with and Nix makes it fairly elegant to do, depending on what ecosystems it's being used with.
Using NixOS to manage your whole system, on the other hand, I don't think I'll ever get behind. Maintaining reproducible builds of my system, while being nice to have, doesn't really solve any problem that I actually have. On the other hand, it introduced a myriad of problems that plagued me on a regular basis before I switched away from it.
The first problem I had was that it added steps to a number of tasks I had on a regular basis. For example, updating or adding new extensions to VS code. Because NixOS is immutable, you don't get to benefit from just running a single update or install command within VS code like you would on a normal system. It becomes an annoying series of steps you have to carry out for each operation, all in the name of being convenient to hypothetically down the line. Multiply this by all the tools you use and it gets tiresome.
The other issue is that you raise the barrier of entry for every new piece of technology you want to experiment with. Now, in addition to learning how to use any tooling involved with the ecosystem, you have to figure out how to get it to play nicely with Nix. This works very well for some ecosystems, like Haskell, and not well at all for others. I was just getting started with Android development at the time, and just when I thought I had it working nicely with Nix, I would run into a new problem that would need investigation and band-aids.
I wish NixOS was more convenient to use than it was in my experience, because it's nice when it works well. But in my case it created more problems than it solved.
Nix builds suck for development because there is no incrementality there. Any source file changes in any way, and your typical nix flake will rebuild the project from scratch. At best, you get to reuse builds of dependencies.
> while much of that build time is attributable to Nix's way of building dependencies
And that part just doesn't make sense to me. I can't see any way in which specifically Nix's way of building dependencies would contribute to this. The compiling of the universe, sure, but then why mention Nix?
> Nix only partially solves the problem by better supporting concurrent installation of multiple versions of those dependencies. But those concurrent versions would still each have to be maintained
How so? Every dependency of every dependency is in the nix store and they’re all immutable. A nix package installed will work forever because its environment can’t change. Am I not right?
I've read people admitting that Nix can give you a lot of work from time to time, when something isn't already available for Nix (which happens more often than, say, for Debian), and you want to add it to your system. Is that true in your experience? I may be phrasing it wrong.
reply