1. 53

  2. 25

    So ditch your version manager, and use … a different version manager? One that I have to find the specific nixpkgs SHA if I want a specific version of the package I need.

    Does this let me install an old version of Python AND the latest nodejs? I suspect not, but please correct me if this is possible.

    I’m personally very happy with asdf and its meta-version manager capabilities, but you do you.

    1. 22

      The article espouses discarding all package-specific version management. The hope is that multiple distinct packaging systems can be ignored in favor of a single holistic ports tree.

      $ nix-shell -p python27 nodejs_latest
      $ node --version
      $ python2 --version
      Python 2.7.18

      Close enough. All versions can be fine-tuned, but ultimately even the most pedantic versioning policy usually crumbles before Nix’s pragmatism; you probably don’t need “the latest” version of most packages.

      Note that asdf’s documentation itself admits that asdf does not aim for reproducibility. This means that while your configuration may reliably work for you on your machines, it may take others a long time to reproduce your results.

      1. 12

        The article mentions how you can do that. In short:

          pkgs = import <nixpkgs> { };
        pkgs.mkShell {
          buildInputs = [
            pkgs.python27Full # old python
            pkgs.nodejs-16_x. # latest node

        If you want a specific version that is not present, you can create an overlay and change the version to whichever you need (see this diff as an example).

        The title refers to the fact that, in my view, your current version manager does not do enough. It should also include tooling that you need to run the project and make sure each program’s dependency tree is explicitly marked.

        1. 3

          Sibling comments are correct but also point out only Python and Node.js versions that are current in Nixpkgs. This doesn’t necessarily differ from other package managers and repositories. At some point, old versions are kicked out, usually some time after upstream drops support.

          What’s different however is that you can pin multiple versions of Nixpkgs as well. You can pull an old, unsupported Python version from an old Nixpkgs, and use the latest Nixpkgs for everything else, like Node.js.

          But you’re right, still have to find that Nixpkgs SHA. (I don’t often do this, though? More often, I end up sticking to some last-known-working SHA.)

          1. 2

            Thank you. I realized my scenario wasn’t clear but you addressed it. Mixing multiple versions of nixpkgs is exactly what I was looking for.

        2. 13

          Genuine comment (never used Nix before): is it as good as it seems? Or is it too good to be true?

          1. 51

            I feel like Nix/Guix vs Docker is like … do you want the right idea with not-enough-polish-applied, or do you want the wrong idea with way-too-much-polish-applied?

            1. 23

              Having gone somewhat deep on both this is the perfect description.

              Nix as a package manager is unquestionably the right idea. However nix the language itself made some in practice regrettable choices.

              Docker works and has a lot of polish but you eat a lot of overhead that is in theory unnecessary when you use it.

            2. 32

              It is really good, but it is also full of paper cuts. I wish I had this guide when learning to use nix for project dependencies, because what’s done here is exactly what I do, and it took me many frustrating attempts to get there.

              Once it’s in place, it’s great. I love being able to open a project and have my shell and Emacs have all the dependencies – including language servers, postgresql with extensions, etc. – in place, and have it isolated per project.

              1. 15

                The answer depends on what are you going to use nix for. I use NixOS as my daily driver. I am running a boring Plasma desktop. I’ve been using it for about 6 years now. Before that, I’ve used windows 7, a bit of Ununtu, a bit of MacOS, and Arch before. For me, NixOS is a better desktop than any of the other, by a large margin. Some specific perks I haven’t seen anywhere else:

                NixOS is unbreakable. When using windows or arch, I was re-installing the system from scratch a couple of times a year, because it inevitably got into a weird state. With NixOS, I never have to do that. On the contrary, the software system outlives the hardware. I’ve been using what feels the same instance of NixOS on six different physical machines now.

                NixOS allows messing with things safely. That’s a subset of previous point. In Arch, if I installed something temporarily, that inevitably was leaving some residuals on the system. With NixOS, I install random on-off software all the time, I often switch between stable, unstable, and head versions of packages together, and that just works and easy rollbackabe via entry in a boot menu.

                NixOS is declarative. I store my config on GitHub, which allows me to hop physical systems while keeping the OS essentially the same.

                NixOS allows per-project configuration of environment. If some project needs a random C++ package, I don’t have to install it globally.


                Learning curve. I am a huge fan of various weird languages, but “getting” NixOS took me several months.

                Not everything is managed by NixOS. I can use configuration.nix to say declaratively that I want Plasma and a bunch of applications. I can’t use NixOS to configure plasma global shortcuts.

                Running random binaries from the internet is hard. On the flip side, packaging software for NixOS is easy — unlike Arch, I was able to contribute updates to the packages I care about, and even added one new package.

                1. 1

                  NixOS is unbreakable. When using windows or arch, I was re-installing the system from scratch a couple of times a year, because it inevitably got into a weird state. With NixOS, I never have to do that. On the contrary, the software system outlives the hardware. I’ve been using what feels the same instance of NixOS on six different physical machines now.

                  How do you deal with patches for security issues?

                  1. 8

                    I don’t do anything special, just run “update all packages” command from time to time (I use the rolling release version of NixOS misnamed as unstable). NixOS is unbreakable not because it is frozen, but because changes are safe.

                    NixOS is like git: you create a mess of your workspace without fear, because you can always reset to known-good commit sha. User-friendliness is also on the git level though.

                    1. 1

                      Ah I see. That sounds cool. Have you ever had found an issue on updating a package, rolled back, and then taken the trouble to sift through the changes to take the patch-level changes but not the minor or major versions, etc.? Or do you just try updating again after some time to see if somebody fixed it?

                      1. 4

                        In case you are getting interested enough to start exploring Nix, I’d personally heartily recommend trying to also explore the Nix Flakes “new approach”. I believe it fixes most pain points of “original” Nix; two exceptions not addressed by Flakes being: secrets management (will have to wait for different time), and documentation quality (which for Flakes is now at even poorer level than that of “Nix proper”).

                        1. 2

                          I didn’t do exactly that, but, when I was using non-rolling release, I combined the base system with older packages with a couple of packages I kept up-to-date manually.

                  2. 9

                    It does what it says on the box, but I don’t like it.

                    1. 2

                      I use Nixos, and I really like it, relative to how I feel about Unix in general, but it is warty. I would definitely try it, though.

                    2. 7

                      Installing direnv with brew is a disappointing start, especially since nix-shell works fine without it. I admit the experience is superior with it, however: I just think the article is burying the lede.

                      Not a bad article overall, but barely scratches the surface of what Nix has to offer. If it piqued your interest, I would recommend https://blog.sulami.xyz/posts/nix-for-developers/ (disclaimer: by a colleague of mine), especially if you’re on macOS.

                      1. 3

                        I don’t understand this “pin the channel git SHA” part of the process. Say I have some software environment in production that runs with fixed versions of nodejs, pan doc, and postgres. How do I find the right Nix SHA that contains the desired versions of all of those packages? If such a SHA doesn’t exist, what do I do? Find the best SHA for the majority of the packages then go back to installing the rest manually with a shell script? Sounds like a Dockerfile with a much more difficult specification language.

                        1. 8

                          The idea of pinning a sha is that all packages in the nixpkgs repo are guaranteed to work together for any given sha. For the most common programs, nix ships multiple versions by default to make it easy to switch between versions (nodejs has 10/12/14/16, postgres has 9.6/10/11/12/13). If you need exact dependencies you can create an overlay to specify the exact version of the dependency that you need.

                          The advantage over a Dockerfile is that in Nix each program can depend on their own versioned set of dependencies: so you can have program hello depending on libyaml-0.12 and program goodbye depending on libyaml-0.13. In Nix they can co-exist peacefully without interfering with each other.

                          1. 3

                            Technically you don’t even need niv to do that either. You can encode the sha you wish to pin right in the default.nix.

                            In fact both niv and direnv in the examples are unnecessary technically although they may make some things a little easier.

                            1. 1

                              How do I find the right SHA?

                              1. 4

                                I wrote a tool to help do that:


                                1. 1

                                  Usually you pick a released nixpkg version. This page gives a pretty decent overview of the various methods to pin stuff. https://nixos.wiki/wiki/FAQ/Pinning_Nixpkgs

                                2. 1

                                  OP here: completely agree that niv and direnv are technically unnecessary :) I wrote the post with in mind a complete Nix beginner that doesn’t really want to run nix-shell or pin nixpkgs manually, or learn how to use Nix flakes. I’ll use it as a resource to point people that are curious about Nix and want to try it without having to understand too much in depth how it works.

                              2. 1

                                One thing I use pyenv/rbenv for is managing multiple versions of python or ruby. In this approach would that require installing and uninstalling software each time? What if I’m offline when I want to switch between versions?

                                1. 3

                                  I’m doing the same with shell.nix per project. Software is installed once, until garbage collected. You can create a reference to the project, so nix will not garbage collect it. I suppose that if you’re offline, just copying shell.nix from one project on your machine to another would at least give you exact same version of python/ruby, without needing to download anything. Of course, for anything on top, you’ll probably have to download stuff.