Hacker News new | ask | show | jobs
by soraminazuki 1530 days ago
I have the exact opposite experience. Nix is the best solution out there especially in the sort of situations that you describe.

Nix provides a level of flexibility that other solutions simply do not offer. If a package in Nix doesn't fit your requirements for whatever reasons, you can create a modified version of a package with ease. For example, say that you need a version of Nginx built against a custom version of OpenSSL. You can do just that with a few lines of code:

    let
      mypatch = pkgs.fetchpatch {
        url = "https://example.com/bugfix-for-openssl.patch";
        sha256 = "...";
      };

      openssl = pkgs.openssl.overrideAttrs (old: {
        # add build flags
        configureFlags = old.configureFlags ++ [ "--enable-foo" ];

        # add dependencies
        buildInputs = old.buildInputs ++ [ pkgs.foo ];

        # add patches
        patches = old.patches ++ [ mypatch ];
      });
    in
    nginx.override { inherit openssl; }
Nix will even know which packages it'd need to build locally instead of downloading a prebuilt binary.

You can't do that with other common package managers. You're stuck with whatever the package manager provides you. So if you're not in the happy path, you're out of luck. You'd either have to give up or build from scratch. If you need a bugfix for a particular package, you'd have wait until the fix reaches the package repository. When I was using Ubuntu, that was often until the next major release. None of this stuff is a problem with Nix, which allows for customization with very little effort.

It's easy to learn about Nix if you know where to look for. Nix Pills [1] would be a good start. The core language is the easiest part. It's JSON, but with functions and variables for proper abstraction. The documentation, while imperfect, is quite extensive compared to a majority of other high profile open source projects. If the documentation fails you, the Nixpkgs repository [2] is an even more rich source of information. The code is well organized, and I was able to get familiar with writing Nix packages fairly quickly by grepping the codebase. And finally, Nix has a sizable community so you could always ask if you're stuck.

[1]: https://nixos.org/guides/nix-pills/

[2]: https://github.com/NixOS/nixpkgs

5 comments

> It's easy to learn about Nix if you know where to look for.

I understand you are saying it with the best intentions but it might sound like not the most correct way of defending a tool being criticized for its lack of documentation or easy of use.

I feel that the criticism regarding documentation is too harsh. Speaking from experience, Nix has more documentation and community resources than most open source projects that I've encountered.
Most open source projects have a woeful lack of community resources and documentation though, so that’s not really saying much.

Ultimately documentation doesn’t solve usability problems it just makes note of them.

Your example looks great! Indeed I trolled every piece of nix documentation I could find -- it was the only way to figure out what I should be doing.

Here's the simplest example of an utter failure when I tried nix: installing ruby 2.2. It's very possible I did something totally wrong, but when I have to use ruby 2.2 and nix cannot do it, it sort of kills your awesome example of being able to override openssl.

Another extremely frustrating experience was the bifurcation between nix and nixos. Clearly one experience is preferred over the other. So many blogs and docs talk about things like HomeManager and other configurations that are nixos specific.

On top of nixos/nix, there's also shell.nix/flakes. There's just too much development in nix right now to make sense of what's going on.

> when I have to use ruby 2.2 and nix cannot do it

Considering that ruby 2.2 was released in 2014, I can't say I'm surprised. It's too much effort to continue maintaining something so old. But if you really want to use it, you could try using the package definition from an older commit of Nixpkgs:

    let
      nixpkgs1709 = pkgs.fetchFromGitHub {
        owner = "NixOS";
        repo = "nixpkgs";
        rev = "e09c0adc63d10249dac8f90313f91e1050861d3c";
        sha256 = "sha256-Di9D0gvaESV3JmX/kW2uEJ68QDlAke23t19bImTXsJ8=";
      };
    
      pinnedPkgs = import nixpkgs1709 { };
    in
    pinnedPkgs.ruby_2_2
> Another extremely frustrating experience was the bifurcation between nix and nixos.

I'm not sure what you mean. Nix is the package manager while NixOS is an entire distro based on Nix the package manager and its configuration language. They have clear separation of concerns. Keeping it that way has actual benefits too, namely portability. It allows you to use Nix on a wide range of platforms including non-NixOS Linux distros, macOS, and even BSDs to some extent.

> On top of nixos/nix, there's also shell.nix/flakes.

Flakes are currently an experimental feature and not meant for wide use yet. So if you're just getting started with Nix, I'd recommend looking into it later until you're sufficiently comfortable with Nix.

They're not fundamentally different, though. Flakes formalize the conventions for writing Nix expressions to make them more reusable.

You don't need NixOS for Home Manager. It's actually the first chapter in the installation section: https://nix-community.github.io/home-manager/index.html#sec-...
Thanks for that clarification. My point was mainly that I was being led down paths that were talking about home manager which was something I didn’t want in my system. Nix, nixos, home manager, flakes, shell.nix … they all do different things and blog articles and documentation mix and march them to create a very confusing ecosystem to navigate.
Flakes are actually part of the piece for how to sanely get access to old versions of things, as your project flake can bring in multiple instances of nixpkgs from different “stable” branches and then pull the specific packages off each one that you need.
Just in this thread I have one person saying that I should avoid flakes and you are telling me it will save me. I think we proved my point.
Fair, fair. A slightly more charitable take might be that flakes solve/streamline a set of problems that are particularly acute for power users, and installing multiple specific versions of software without needing to copy the definitions into your overlay is absolutely a power user move.
Flakes are undeniably useful but it's gated behind an experimental flag and documentation work is ongoing. For now, it just shouldn't be the first point of entry for beginners.
The documentation is the biggest gap for sure. I've only been using Nix for about a year, and I'm using flakes exclusively. Although I don't have direct experience with the legacy system, I could definitely picture it being very frustrating managing inputs via the NIXPATH envvar rather than explicitly with flake locking.
Did you ever try using Ruby 2.2 in an isolated nix-shell? That's arguably the best feature of nix-shell, to create an isolated environment with only the packages you need for that particular project.
This is the best comment I've read on nix yet!

I've been using nix as my daily OS for six months and I'm able to be productive. At the same time, I'm often confused as to whether I should use nix-shell, nix-env or modify my configuration files.

Thanks for the great comment.

I'm new to NixOS too. My general rule is to try to keep my core system build/description as minimal as possible. Default to nix-shell first, and only if I'm using that thing repeatedly do I then test-install it with nix-env, and if that succeeds then add it to configuration.nix.
It is both great and terrible, a shining example for me was that I wanted to install a package built off a specific commit. That was trivial, I just over rode the source and the expected hash and the exact same build & install steps worked.

Also rollbacks in nixos are amazing.

On the other hand newly packaging something can be really daunting.

What problem is this solving that a shell script couldn't handle for you? I don't know anything about nix, genuinely curious.
The example above is part of a declarative, reproducible, full system build. You include it in your build description file, and then Nix will rebuild the entire system in the exact same way across multiple machines.

That's less of a guarantee with a collection of shell scripts.

With a shell script, you get to enjoy all the pains of building software and its dependencies from scratch. Even then, you wouldn't be even halfway done. You'd also need to go through the process of turning your ad-hoc procedures into a reproducible script only to find out that it broke months later.

Nix provides better abstractions and composability to make that experience far less painful. Note that in my previous example, I didn't need to specify how to build OpenSSL or Nginx. I was able to reuse the definition from Nixpkgs and apply my own customizations to it.