1. 50
  1.  

  2. 23

    Nix is one of those tools where you don’t know what you aren’t getting until you get it. There are so many things wrong with this post, but I only know that because I spent weeks wrestling with lots of those issues myself.

    You basically need to read all the nix pills (https://nixos.org/nixos/nix-pills/), the nix manual, the nixpkgs manual and the nixos manual in a loop gradually filling in what is going on… which takes a long time.

    Nix is very confusing at first, but enables things that you would not have thought possible once you know what you are doing. The core people don’t seem to evangelize much because it is just one of those tools that solved their problems so well, they don’t have to care about the outside world anymore.

    I use nixos for my laptop, desktop and a few servers, have all my machines config under version control and can roll the machines back to any version whenever I want, remote administer them, build an install on one computer, test it in a VM and then ship it with a single command to another machine. I won’t go back to another OS despite there being room for improvement, because no other OS comes close in terms of what you can do (my path has been windows -> ubuntu -> arch linux -> freebsd -> openbsd -> nixos).

    1. 18

      I use NixOS on everything and completely agree. It’s a massive investment. It was worth it for me, but it shouldn’t have to be a massive investment. Need better tooling and docs.

      1. 5

        Yeah, there are lots of things I wish I could explain, but the explanations take a large investment. Take for example the complaint about making a new language instead of using something existing… It seems sensible on the surface, until you understand deeply enough to know why laziness is needed, and features like the pervasive use of interpolation to generate build scripts… Once you understand those, you know why a new language was made.

        The lack of tooling IS a valid complaint, and the fact the language isn’t statically typed could also be a valid complaint, but the community is growing despite all those issues, which is a good sign.

        1. 6

          I’m hoping https://github.com/haskell-nix/hnix will help with that point, and the tooling.

      2. 6

        You basically need to read all the nix pills (https://nixos.org/nixos/nix-pills/), the nix manual, the nixpkgs manual and the nixos manual in a loop gradually filling in what is going on… which takes a long time.

        I’ve tried reading all of this but I found it all horribly confusing and frustrating — until I read the original thesis on it, which I still think is (perhaps surprisingly) still the best resource for learning how nix works. It’s still a pretty big investment to read, but imho it’s at the very least a much less frustrating experience than bouncing from docs to docs.

        (I wonder if the same is true of the NixOS paper?)

        1. 3

          How do you manage secrets in configuration files? Passwords, ssh keys, tls certs and so on. If you put them into a nix-store they must be world-readable, right?

          One could put a reference to files outside the store in configuration files, but then you loose a bit of the determinism of NixOS and it’s not always easily possible with third-party software to load e.g. passwords from an external file anyways.

          Besides the learning curve, that was the single big problem which kept me from diving deeper into the nix ecosystem so far.

          1. 7

            You are right, no passwords should ever go in the nix store.

            The encryption key for my backup script is in a private root owned file I put under /secrets/ . This file is loaded in my cron job so the nix store simply references the secret but doesn’t contain it. This secret dir isn’t under version control, but is backed up with encrypted backups.

            Every daemon with secret config I have seen on nixos has a “password file” option that does the same thing.

            1. 3

              How do you manage secrets in configuration files?

              For my desktop machine I use pass with a hardware key. E.g. nix (home-manager) generates an .mbsyncrc with

              PassCmd "pass Mail/magnolia"
              

              For remote machines, I use nixop’s method for keeping keys out of the store:

              https://nixos.org/nixops/manual/#idm140737318276736

            2. 1

              Nix is one of those tools where you don’t know what you aren’t getting until you get it. There are so many things wrong with this post

              I have to disagree, but not with the second sentence - I was sure as I wrote the post that it was full of misconceptions and probably outright errors. I wrote it in part to capture those in the hopes that someone can use them to improve the docs.

              But to disagree with the first sentence, I was keenly aware through the learning and writing that I was missing fundamental concepts and struggling to fill the gaps with pieces from other tools that didn’t quite fit. If there is indeed a whole ‘nother level of unknown unknowns, well, that’s pretty disheartening to me.

              1. 1

                I can’t speak for your experience, but that’s how it was for me anyway, on the plus side it also meant nix solved more problems I was having after I understood better. I even thought nix was over complicated to the point I started writing my own simpler package manager, only to find nix had solved problems I ran into before I knew what they were.

            3. 13

              Oh boy. Here, have a hopefully helpful anecdote…

              I spent a lot of time, sweat, tears, and pain deciding to “properly” learn Nix to set up armokweb, aka lobste.rs plays Dwarf Fortress. I’ve yet to do a full writeup/postmortem (although I intend to), but I finished the first iteration of that project with a mostly-positive view of NixOS from no experience whatsoever.

              First, let me get it out of the way: the documentation often sucks and you have to read other packages that do a similar thing to the package you want to write to create custom packages at all. There’s not really a “Nix package cookbook” like there should be. Nix Pills gets you part of the way there, but my perception is that the whole nixpkgs contribution process operates on screwing up and learning from maintainers who have more experience than you.

              nixpkgs is beholden to how well the community maintains it, but this is similar to Arch’s situation with the AUR. If there were fewer maintainers, the AUR would not be as useful. Some Nix packages (including the dwarf-fortress one, which I ended up contributing to) had breaking bugs. I’m not sure I’m qualified to argue for how “mature” nixpkgs already is, but it’s definitely getting better.

              On a more positive note, I like Nix’s immutable packages and declarative approach to configuration. I tested armokweb in a Nix VM, and it was near-trivial to refactor it so it ran in a container that could be included in a Nix config with two lines of code. Nix’s strong point, IMO, is that it encourages you to produce artifacts (Nix code) that can be used to reproduce a system configuration on another machine, or in a container, or in some other context within the system. Coming from Debian, CentOS, and Arch, it’s a godsend that this is included in the OS and you don’t have to separate the steps of configuration and reproducing that configuration for others to use as much as you would with something like Ansible. It’s also great that you can mix rolling and non-rolling release models all you want. Your entire system doesn’t have to be “unstable” - just the packages and maybe their dependencies that need to will be if you decide to install an “unstable” package. There are no dependency diamonds that cause apt to complain that the wrong version of libc is installed if you accidentally add the wrong mirror.

              Nix the language is sort of like a weird Python/ocaml hybrid, but the lazy evaluation approach works really well for package management. Derivations stringify to their Nix store path, which is the content address of that package (and, when they’re depended on, they get loaded, either from local build via cryptographic content-hash or from cache). It’s why the NixOS cache can exist as effectively just that, a cache that just makes installing packages go faster because they’re on a nearby server instead of needing to be rebuilt locally.

              Overall, I’m a fan of NixOS. The entirety of system configuration is filling in the blanks in a playbook that you can share with others. Packages have strong guarantees about their integrity. Nix the language is a little weird but workable once you’ve seen enough of it. Containers just use lxc and lots of hardlinks to function. I’d like to see deeper integration with ZFS for managing the Nix store. Currently, garbage collection is done at a user-facing FS level, when Sun Microsystems solved this problem years ago at the block level.

              I think there’s plenty to like about what NixOS provides, with the caveat that they can do all this better down the road. I feel like it would be really informative for them to refactor the Nix store so it’s able to take advantage of the features of ZFS. OpenIndiana already uses ZFS to manage system “generations” in a similar way to how NixOS uses symlinks and hardlinks. They would be able to make their OS better if they learned more from IllumOS, but I have no doubt that they could tackle that if they wanted to.

              1. 2

                I’ve heard lots of good things about ZFS, but it smells a bit too monolithic in my (inexperienced) opinion. I can certainly imagine the benefits of setting it up on a server, for example; but I don’t like the sound of a general purpose, publically available, userspace application like Nix relying on its functionality (i.e. forcing users to adopt ZFS just to run that particular program).

                Maybe NixOS, as a full-blown distro, could encourage use of ZFS in its installer; I think there’s still debate raging about the legalities of bundling things like that. Also, I’m perhaps a little out of touch with the NixOS installation process: I installed 16.03 in 2014 and have been upgrading rather than re-installing since then. Also my experience was a little unorthodox: I used the CD ISO image, but since I don’t have an optical drive I ran the installer from within qemu (potentially dangerous, since it was installing to the same /dev/sda drive as the host, and very slow since my CPU doesn’t have virtualisation extensions :P )

                1. 2

                  it smells a bit too monolithic in my (inexperienced) opinion

                  It definitely is, but I also wouldn’t have as many reservations about putting a NixOS root on ZFS if it could be implemented that way. At present, it’s a file level GC on top of a block level GC. It doesn’t even have to be a hard dependency, especially if it’s implemented with ZFS channel programs, which are a new feature in ZoL that lets root run Lua scripts that implement custom ZFS behavior in the kernel. Read-only mounts of snapshots are just exactly how the Nix store’s implementation currently behaves, and Nix might as well take advantage of features of the filesystem if it has them available.

              2. 5

                For those trying to learn Nix, I highly recommend learning the Nix language using the REPL. If you’re on a 1.x version of Nix (or NixOS < 18.03) you can use the nix-repl command provided by the nix-repl package, e.g.

                $ nix-shell -p nix-repl --run nix-repl
                

                If you’re on Nix 2.x or above (or NixOS 18.03 or later) this is now built-in to Nix, just run:

                $ nix repl
                

                For Nix 2.x there’s also the --show-trace option which will give you more debug info if there’s a failure.

                One gotcha with the REPL is that it will sit waiting for input if it’s given an incomplete expression, even if that expression is from an external file! For example:

                $ echo "''unterminated string" > foo.nix
                $ nix repl --show-trace
                Welcome to Nix version 2.0.4. Type :? for help.
                
                nix-repl> import ./foo.nix
                

                This will hang, presumably waiting for the ''. This is usually obvious for things like strings, but less obvious for e.g. expressions which contain ; like with foo; bar or assert foo; bar (those semicolons aren’t terminators, they’re separators, hence the following expression (bar) is required, or else it’ll hang like above)

                1. 5

                  I really want to love NixOS: the ideas, the tools, how things are supposed to work… All they propose sound like future to me. Be able to have my config, which defines how I want my computer to behave, and just plug it in all the machines I may need to use sounds mindblowing.

                  And personally, I am finding the learning curve to be steep as hell. Not only because the documentation seems to assume that the one reading is slightly familiar with the environment and how things work, also because I need to modify certain habits to make them work with NixOS. For example, one of the must-haves for me is my Emacs configured as I like. I can tell Nix to clone my Emacs configuration to the home folder, and it should already be able to start downloading the packages it needs; but in reality that is not trivial because it seems to expect the packages to be downloaded from the Nix configuration instead of the Emacs one (to ensure the system to be deterministic, it makes absolute sense). I am used to have everything available from everywhere, but NixOS has most things isolated by default to keep the purity.

                  I will keep on fighting with stuff until I find things out, but I am sure that as the project grows all these corners will be polished to make it more accesible to newcomers.

                  1. 5

                    For what it’s worth, I’ve been a heavy user of Nix, NixOS and Emacs for years, but still haven’t bothered configuring Emacs with Nix. The Emacs package I use is emacs25.override { withGTK2 = false; withGTK3 = false; } (this causes it to compile with the lucid toolkit, avoiding http://bugzilla.gnome.org/show_bug.cgi?id=85715 ). I do everything else with a ~/.emacs.d that’s been growing for years, across various distros, and is a mixture of Emacs Prelude (which I started with), ELPA/MELPA/Marmalade and (more recently) use-package. I just install any dependencies into my user profile or NixOS systemPackages. Actually, I define a package called all which depends on everything I want; that way I can keep track of it in git, rather than using commands like nix-env which can cause junk to accumulate. It looks like this:

                    with import <nixpkgs> {};
                    buildEnv {
                      name = "all";
                      paths = [
                        abiword
                        arandr
                        audacious
                        cmus
                        (emacs25.override { withGTK2 = false; withGTK3 = false; })
                        gensgs
                        mplayer
                        picard
                        vlc
                        w3m
                        # and so on
                      ];
                    }
                    

                    There are certainly some aspects of Nix which require “buy in” (it looks like Guix is slightly better in this regard), but there are others which allow “business as usual”.

                    For example, if you want to make a Nix package that just runs some bash commands, you can try runCommand, e.g.

                    with import <nixpkgs> {};
                    runCommand "my-package-name" {} ''
                      # put your bash commands here
                      # the "result" of your package should be written to "$out"
                      # for example
                      mkdir -p "$out/bin"
                      printf "#!/usr/bin/env bash\necho hello world\n" > "$out/bin/myFirstProgram"
                    ''
                    

                    Whether this will work obviously depends on what the commands do, but if it works then it works (you can even run stuff like wget, git clone, etc. if you want to; although I’d include a comment like TODO: use fetchurl or fetchgit). If your scripts need env vars to be set, put them between the {}. If you want some particular program available, put buildInputs = [ your programs here ]; between the {}.

                    Another example is programs which assume the normal FHS filesystem layout: making them work is sometimes as easy as using steam-run (e.g. https://www.reddit.com/r/NixOS/comments/8h1eu5/how_do_you_deal_with_software_that_is_not_well/ ).

                    Whilst there’s complicated infrastructure in Nixpkgs to support packages which use Python, Haskell, autotools, etc. sometimes we can get away without having to go ‘all the way’ :)

                    1. 2

                      Woah, thank you, that was super useful! I think I got it, but I still have to test it and have my own gotcha moments :)

                    2. 4

                      When starting out I just built a few packages from source in the traditional way to make them work the way I was used to, perhaps that could work with emacs and install into home initially. (I don’t use emacs, sorry I can’t help more.)

                      1. 2

                        You’re not alone - I installed NixOS recently and like what I’ve seen, but haven’t been able to put in enough time to get over the learning curve yet. Until I do, I’m fairly sure I’m missing several chances to “do things properly” because I’m not sure what that looks like under NixOS. This post and comments have been quite reassuring at least!

                        I guess that’s the beauty of open source - now we all have to go and fix the documentation?

                        1. 2

                          I guess that’s the beauty of open source - now we all have to go and fix the documentation?

                          Well… I guess. I’ll make some coffee.

                      2. 4

                        Does anyone know if there’s been any more recent progress on getting FreeBSD support (back) into Nix?

                        I’d loooooove to try out Nix especially for stuff at work but not supporting FreeBSD is currently a deal-breaker.

                        1. 3

                          On a related note, is there any support planned for OpenBSD?

                        2. 3

                          Thanks for this! I spent a while trying to get Nix to work on PRGMR but gave up at some point :’(

                          1. 5

                            Since you gave NixOS a try in April @cmb put together a netboot installer and added notes on installing NixOS to our wiki. The process is better documented now, in part from your willingness to experiment with it earlier this year.

                            1. 3

                              Oooh, gee! That’s exciting :) Thanks!

                          2. 3

                            I then turned to the Nix manual to learn more about working with and creating packages and failed, even with help from the nixos IRC channel and issue tracker. I think the fundamental cause is that it wasn’t written for newbies to learn nix from; there’s a man-page like approach where it only makes sense if you already understand it.

                            I very much agree with that. Like it’s mentioned in the intro Nix has been mostly designed bottom-up and it shows in the UX. In that regard it’s a bit like Git. It solves a fundamental problem (no more cache invalidation issues!) but requires the user to go through the long and painful learning journey until they emerge from the other side.

                            On the other end of the spectrum, Homebrew has the best package manager UX that I know of. It’s very easy to create new packages, the CLI is easy to use and has a nice and colored outputs with helpful error messages. It’s just not that robust so one has to cleanup things regularly. Or link/unlink packages when different versions of things are needed.

                            By the way the Nix community is aware of those issues but we don’t have a UX-first team that has been formed yet. And fixing things like that takes a long time but I still have hope.

                            1. 2

                              For new comers I recommend to ask questions and search the Discourse forum at https://discourse.nixos.org/

                              We are starting to have good content there and questions get answered. The longer form allows to better expand on questions in my experience.