What's all the hype with Nix?

I agree!

Pinning project dependencies is a great practice, regardless of the size of your team, and regardless of how you do it. Nix is a good way, and you can do it in other ways as well. Floating dependency versions will eventually bite you if you don’t pin those.

2 Likes

Many good answers here, but there is another perspective too I would like to add:

For many of us, the usual situation where computers are full of random…stuff, opaque binaries that might be compiled open source but it’s not clear how, is an annoyingly messy situation. It feels like not really being in control of one’s machine, and that all these dark dusty corners make everything more complex that need be because it’s impossible to tell what is actually needed vs what is just there.

Nix and it’s ecosystem together is a solution to that problem by allowing when to have a “complete blueprint” for all the software on their machine.

Nevermind how Nix works, or that it was inspired by functional programing. I think this appeals to the same sort people who also get into Haskell in the first place. If Haskell inspires the dream that all the junk could be rewritten, Nix inspires the dream that we can at least clime on top of the current garbage heap to get a better vantage point!

6 Likes

Not if you want bugfixes and security patches. That’s why PVP and semver were invented.

5 Likes

Can I chime-in with a “to the core” explanation.

Linux ecosystem & IT as a whole - is a huge “bazaar” development process. It creates a structural mess as a biproduct. There are ~20 package managers & ~+100 central distribution software repositories.

The biggest repository that is famous for being usable & have almost all of the software packages - is Arch Linux sidekick AUR (Arch User Repository). AUR has 1 major design flaw - every package needs(encourages) a separate repository just for that package configuration, & so only one particular maintainer of that repository & package (the strong “bus factor” there - maintainer is not responding - nobody can do anything about the package), all package configurations are a separate configuration. It is a bit of a hassle to contribute to AUR - because every time the new repository must be cloned & the patch is on the mercy of 1 particular person in the world giving attention to the patch.

In the DevOps/SRE space - specialists need to learn/know several hundred tools & ~20 domain-specific languages to put all that together. Docker, Ansible (great language but not centralized), Hashicorp (HCL - great language), Kubernetes (its overengineering complexity of configuration & its repetitiveness & formatting - is what drove me away from DevOps, apart from learning & understanding the main classical DevOps tools language - Go) - it is just a beginning of what DevOps/SRE is about - a 50% of a job there is putting things together & keeping updates to those parts in sync with one another, it is a job largely about “bridging the gap” in structural disorganization.

Main DevOps/SRE invention is keeping infrastructure as a code.

& here comes Nix.
Nix language is (because of its scientific properties of it) - is a powerful language, it to put simply - infinitely programmable. So “infrastructure as a code” can be achieved (from the beginning - downloading, configuring, installing a package; to the end: managing a 1 000 node cluster deployment of servers with 100k “containers”, on cloud provider (& its services) running an enterprise software services that is the main source of company money). Nix language “laziness” allows to put all configuration for the world of software into 1 repository & grow the codebase there infinitely. So the world of people can pile-on unto 1 repository & polish & polish it & maintain it. Changing 1 structural thing in Nixpkgs - affects not 1 package, as in AUR - Nixpkgs maintenance allows to do a sweeping functionality introduction, compatibility changes & refactoring changes - across the whole world of computer software at once. The only caveat of it - is that Nix language & its complexity & complexity of a tooling, working with it & consequences of a design approach.

Nix gives DevOps/SRE a completely new perspective. No DevOps/SRE ecosystems except NixOS (NixPkgs) options - have that level of being a 1-stop candyshop for infrastructure automation deployment:

  1. Kubernetes: NixOS Search - Loading...
  2. PostgreSQL: NixOS Search - Loading...
  3. Grafana: NixOS Search - Loading...
  4. Haskell: NixOS Search - Loading... & Hoogle server: NixOS Search - Loading...

& It is not only DevOps/SRE options, those options are suitable for any deployments, so they also provide just as good Desktop configuration as well.

Those Options get a (now standardized) crowd-maintenance from a worl-wide network of according narrow-specialized professionals, & further general Nix code maintenance is done by NixPkgs maintainer teem as a side-gig of NixPkgs updates & refactors.

Nix puts Open Souce idea of “contributing through scratching one owns itch” - into a proper position, if someone does something - that is contributed to & immediately but gradually used by everyone - so the more people - the more correction & quality. Because of paradigms & context - “quantity transforming into quality” is the most strong here.

I also see NixPkgs as a main testing ground for open source projects being done right. On the integration of a package - if there is any assuming infrastructure/configuration hardcode - it would be found & reported upstream to be fixed. In that way NixPkgs (& Hydra) is a CI for compatibility & portability of software.

Nix actually has no competitors in DevOps/SRE field, no comparable products (besides GNU GUIX that sadly does not has the scale required & enterprise views contradict freedom of software license frequently). Only Nix combines multiple abilities that other solutions adopt into old paradigms through containerization, deduplication, FS snapshotting, jailed package bundling - but all those solutions is a patch-work that is even more diverse & complex than the Nix ecosystem, moreover that approach can not rely as strongly as Nix on crowd-source management of those solutions as one whole.

In business terms, Nix is not “just” “visionary” - it also has an objective scientific & technical superiority and solution got to the level - that further it only can grow and disrupt the market of IT infrastructure management & deployment.

To give some proof that it does a proper science-technical leap is: Graphs - Repology

The complexity of Nix maintenance & tooling is another topic - “errors were made” there & Nix ecosystem bears consequences & tries to solve them.

And Nix is a technical needle, also because of those “errors were made”. Companies can pick or classical DevOps, or Nix DevOps - having two at the same time require the ability to attract & hold a too highly skilled specialists that are few and far between & demand a lot from them. Once a business deployed NixOS infrastructure - in simple terms - it requires or to be torn down, or new deployments to be NixOS also & so hire NixOS DevOps’es. It locks-in companies hard on the stack.

So Nix has all needed to disrupt, seize & hold the market for a long time.

2 Likes

The two work together beautifully! Or they could. Pinning doesn’t prevent rolling upgrades, it just ensures everyone/every environment where code is evaluated is rolling in sync.

3 Likes

Would disagree.

Haskell works with Nix, only because Haskell maintainers in Nixpkgs are constantly churning hard at work in time.
Nixpkgs forms a Haskell set from Stackage with Hackage on top of it, & because Cabal & Stack configurations are different from Nix code - so Nixpkgs maintainers need to work quite a lot to keep haskellPackages set.

Also Hackage/Cabal versioning way & Nixpkgs way are different. For example - Cabal would align all tree of dependencies to use 1 version of every dependency, while Nix would not, NixPkgs designed & allows to use one library version for one package & another package in the dependency tree uses a different library version (& Haskell APIs/Hackage/Cabal system does not account for those) - if there are differences in library behavior/code - they can produce deviations.

Nixpkgs standardizes on 1 version & use of older/never versions introduce … work.

From my view the most default way of boot Haskell package into Nix system (considering Nixpkgs being the main software infrastructure) is something like: GitHub - haskell-nix/haskell-with-nixpkgs: Drop-in files ready to integrate your project with Nix ecosystem and give Nixpkgs Haskell Lib abilities for your development and CI.

Until there is a full-blown Haskell community Nix flake.

But people have as many ways to bootstrap Haskell projects - as Turing complete possible. As many projects I’ve seen/maintained - as much Nix bootstrapping setups I saw in projects (as now I also have mine “default one”).

IOHK was hard at work & provided GitHub - input-output-hk/haskell.nix: Alternative Haskell Infrastructure for Nixpkgs, that is a byproduct of their internal struggles & bootstrapping of Haskell projects is just a byproduct of a different agenda of a project & it bootstraps & builds project in a non-conventional way, afaik, does not have caching/build reuse & it does not relate to Nixpkgs infrastructure at all (at the time I studied it).

Bootstrapping to build 1 project in the repository - may be a low effort experience.
While maintaining sizable Nix infrastructure is in itself a full time work.

Nix upstream has a pattern to making implicit changes & approaching from a point that official Nix tooling is the only tooling there, for example, nix in update 2.3.14 to 2.3.15 rolled-out an inNixShell breakage change - that broke all nix shell/default.nix code - without marking mentioning it during release, in docs or changelog, etc… Then in very short order the 2.4 was rolled-out, which additionally broke quite a few things, behaviours in language changed without upstream changing languageVersion & without number of those changes being documented.

Which is why a section of upstream maintainers signed a request to change the status quo on this breakage processes: Nix 2.4, and what’s next? - Development - NixOS Discourse.

Nix should not be simplified - it is quite a complex thing in itself, Haskell & Nix can go together effectively, but there are quite a lot of Nix hurdles & big infrastructure would require a lot of effort & dedicated people on the task. Nix can be simple in project bootstrapping, maintaining middle-size infrastructures probably would be easier through classical means, while maintaining a large infrastructure again classical approach becomes high in maintenance, and so Nix should be easier and long term saves a lot of effort, when there are several people on the task & they can work with upstreams.

At some point I should write something longer. But for now I just want to correct what @Anton-Latukha write about Haskell.nix.

Haskell.nix of course has caching, that’s a fundamental feature of nix. However, Haskell.nix is not constraint to a specific package set. In fact it is much closer to how cabal builds projects. (It really just calls Setup.hs to build each component).

Haskell.nix philosophically just translates a cabal.project or stack project into a nix build plan following resolution constraints from the build tools. This is done by invoking cabal configure on the project to obtain the plan.json, which is then translated into a nix build plan. The only change is that Haskell.nix is able to fairly transparently cross compile Haskell to a given set of targets for which we have TH support. In this respect it significantly exceeds what cabal or stack can do.

The only major complication from nix perspective is fixing the hackage index state to guarantee reproducible builds. For stackage this is given by stackage snapshots.

haskell.nix brings its own set of compilers, so that we can control versions and patches and do not end up with inadvertently changed upstream compilers from nixpkgs.

It’s also orthogonal to nixpkgs, so that changing nixpkgs can be done mostly independent of Haskell.nix (if insulated the Haskell side of things form the system side of things that nixpkgs provides).

On caching: caching can only work if all your dependencies are the same. Thus if you alter any of (nixpkgs, package set, pkg flags, compiler), you inadvertently invalidate any caching you could get. This is not a limitation of nix. You simply can’t get caching for this, with no other system either, if you fundamentally change your build plan you can’t cache anything.
However for a fixed tuple above, you do get caching. Not from the nixos cache, but your hydra or other caching infrastructure. If you happen to use the same nixpkgs, hackage index state and flags as people use at IOG, you’ll most likely find IOGs hydra cache to be helpful. At least for the pre-build compilers.

5 Likes

Thanks. I really love to be corrected & get a proper response on it.

Yes. In short, it probably can be said that haskell.nix is a continuation build & packaging tool line done through Nix. While Nixpkgs is a software distribution & infrastructure approach (& I do think deduplication of effort & maximal automation there). In Nix, I primarily have a vision of & look at the total power of the tool for infrastructure, therefore, mentioned Nixpkgs as a canonical way, I even got a step further & constructed a Nixpkgs integration test for Haskell projects GitHub - Anton-Latukha/test-haskell-nixpkgs-integration-action: GitHub Action that actively tests the project abilty to integrate and work in current official Nixpkgs environemt.

I do often worry about does my projects integrate into Nixpkgs easily.

Your description also reassures me into the usage of haskell.nix. Its design then suits nicely for sharing a development environment between developers of the project.

In any case - Haskellers having a separate flake - would be beneficial. & I do not know about haskell.nix flake to say anything more.

1 Like