There is a similar question on the site which must not be named.

My question still has a little different spin:

It seems to me that one of the biggest selling points of Nix is basically infrastructure as code. (Of course being immutable etc. is nice by itself.)

I wonder now, how big the delta is for people like me: All my desktops/servers are based on Debian stable with heavy customization, but 100% automated via Ansible. It seems to me, that a lot of the vocal Nix user (fans) switched from a pet desktop and discover IaC via Nix, and that they are in the end raving about IaC (which Nix might or might not be a good vehicle for).

When I gave Silverblue a try, I totally loved it, but then to configure it for my needs, I basically would have needed to configure the host system, some containers and overlays to replicate my Debian setup, so for me it seemed like too much effort to arrive nearly at where I started. (And of course I can use distrobox/podman and have containerized environments on Debian w/o trouble.)

Am I missing something?

  • Atemu
    link
    fedilink
    309 months ago

    In this comparison, the devil is in the detail.

    With Ansible, you have an initial condition onto which you add additional state through automatically executed steps dictated by you until you (hopefully) arrive at a target state. This all happens through modification of one set of state; each step receives the state of the previous step, modifies it and passes the entire state onto the next step. The end result is not only dependant on your declared steps but also the initial state. A failure in any step means you’re left in an inconsistent state which is especially critical for the case of updating an existing state which is the most common thing to do to a Linux system.

    In NixOS, you describe the desired target state and the NixOS modules then turn that description into compartmentalised bits of independent state. These are then cheaply and generically combined into a “bundle”; wrapping them into one big “generation” that contains your entire target state.
    Your running system state is not modified at any point in this process. It is fully independent, no matter what the desired system is supposed to be. It is so independent in fact that you could do this “realisation” of the NixOS system on any other system of the same platform that has Nix installed without any information about the state of the system it’s intended to be deployed on.
    This “bundle” then contains a generic script which applies the pre-generated state to your actual system in a step that is as close to atomic as possible.
    A good example for this are packages in your PATH. Rather than sequentially placing the binaries into the /usr/bin/ directory as a package manager would when instructed by ansible to install a set of packages, NixOS merely replaces the bin symlink with one that points at an entirely new pre-generated directory which contains the desired packages’ binaries (well, symlinks to them for efficiency). There cannot possibly be an in-between state where only some of the binaries exist; it’s all or nothing. (This concept applies to all parts that make up a Linux system of course, not just binaries in the PATH. I just chose that as an easy to understand example.)
    By this property, your root filesystem no longer contains any operating system configuration state. You could wipe it and NixOS would not care. In fact, many NixOS users do that on every boot or even use a tmpfs for /.

    (Immutability is a property that NixOS gains almost by accident; that’s not its primary goal.)

    • @[email protected]
      link
      fedilink
      49 months ago

      Very good explanation. It’s an often overlooked property of NixOS and why I often feel like Nix on other systems is an okay way to get packages but you’re missing out on all the good stuff you get through the modules, like losing 95% of what makes the concept good.

      I don’t think NixOS is the best possible solution to the problem, but it’s the only original distribution that even tries to tackle it instead of just working around it.

      • Atemu
        link
        fedilink
        29 months ago

        it’s the only original distribution that even tries to tackle it instead of just working around it.

        Well, apart of GUIX of course ;)

        It’s sort of a conceptual fork of Nix but the actual implementation is all original.

        • @[email protected]
          link
          fedilink
          29 months ago

          I thought so too but learned recently that Guix system is nix under the hood, basically translates everything, so it’s more than a conceptual fork though obviously some more work went into it than your average Ubuntu fork.

          It uses low-level mechanisms from the Nix package manager, but packages are defined as native Guile modules, using extensions to the Scheme language—which makes it nicely hackable.

          https://guix.gnu.org/en/about/

          • Atemu
            link
            fedilink
            2
            edit-2
            9 months ago

            They used to use the nix-daemon to realise derivations but that too was replaced original software at some point I believe. Everything else has been guix own tooling for a long time.

            They still use the same derivation file format (.drv) and the basic concepts are the same (“conceptual fork”), so you could theoretically be able to realise a derivation produced by guix using nix-daemon/nix-store but that’s about it as far as similarities go.

            If you don’t believe me, go take a look at the source code. I promise you won’t find a single line of C++ in it, only a ton of parenthesis ;))))

    • @[email protected]OP
      link
      fedilink
      English
      19 months ago

      Nice, thank you very much for this great summary!

      In my own words, you describe the difference between declarative vs. imperative configuration and the joy of atomic updates. :-)

      I just want to add one point: Theoretically I totally agree, that one might have a bad state in Ansible and the updated state is spoiled, and of course configuration drift is a theoretical problem via Ansible. In practice I never run into this problems in 10+ years of using Ansible. (Of course I treat servers/desktop as cattle, so every major revision of Debian means a complete/clean new installation.)

      • Atemu
        link
        fedilink
        29 months ago

        If it works for you, that’s great.

        I find it a lot more convenient to treat every change about my system as a nearly complete/clean new installation though and NixOS allows you to do so. An upgrade between major versions becomes a walk in the park due to this; it’s the M.O. The last one didn’t require any modification of the config on my NAS. I remotely rebuilt the system from my MacBook Pro with the new channel, rebooted to get the newer kernel and everything worked just like before.

        • @[email protected]
          link
          fedilink
          19 months ago

          An upgrade between major versions becomes a walk in the park due to this

          For personal desktop use, I see nixos and guixos as spending an hour every day, so that you can save minutes every few years.

          When trying out guixos, I spent like 5 days going through the docs and annoying people on irc, just to accomplish the same thing as copying a file to a non-~ directory in a normal distro. Anyways, I powered through the weeks of configuration, and got to actually doing some work in the damn thing. I started off by using the language specific PM to install the dependencies I needed for a project. Welp, guix is not FHS compliant, and can only stand the presence of isolated PMs like nix and flatpak, so that’s out of the question. Since the guix packages were too old, it was time to either:

          • maintain my own guix definitions of random packages + their dependencies, and then maintain a separate source of dependencies for the project
          • learn how to nix and then maintain a separate source of dependencies for the project
          • start figuring out how to use guix to emulate FHS inside of a venv

          So I obviously went for the third option, gave up after banging my head some more, and finally nuked the partition.

          aint nobody got time for that

          Recently I started using home-manager, and tried converting my i3 config so it’s handled by it. Halfway through, it set in just how ugly the syntax looks. I mean just look at a small part from the beginning of both files: nix formatted by nixfmt, i3 config. But ok, I might get used to it, let’s test it out: it fucking added defaults like the keybindings I’ve specifically removed from the config so that the only two i3 deals with are opening the terminal and reloading itself. Then I finally realized I’m wasting my time creating this monstrosity, when literally the only benefit is that it would allow me to skip symlinking directories after a fresh install. So now it’s only managing my packages, doing a great job freshening up stable Debian, and I can reload any config immediately after saving the file instead of going through the entire process of recreating everything home-manager handles.

          I might still use it for some specific packages, like firefox (about:config and custom css), which can’t really be stowed easily.

          Nix and Guix os are brilliant in specific use cases they were made for, like when you’re creating a large number of ephemeral instances for scientific computing and need extremely precise control of everything that goes into the image. Spending a week to configure something simple is worth it in that scenario because it’ll save you from much bigger headaches down the line. The issue is that they solve problems most users simply don’t face, and so the added complexity comes with practically no benefits.

          • Atemu
            link
            fedilink
            29 months ago

            I see nixos and guixos as spending an hour every day, so that you can save minutes every few years.

            I see it more like spending an hour every week so that you can save hours to days of annoying and stressful time every few months.

            Though there are other benefits rather than just time.

            When trying out guixos, I spent like 5 days going through the docs and annoying people on irc, just to accomplish the same thing as copying a file to a non-~ directory in a normal distro

            In the beginning when you’re not familiar with things yet, it always takes more time to do something.

            I didn’t have that particular use-case yet and I’d have to consult at least one manual to do it correctly but I’d nowadays be able to solve that particular problem with one line of relatively simple code in NixOS. (On Guix, I don’t know how I’d do it though since they don’t use systemd.)
            When I started out though? No chance, it’d have taken weeks.

            I started off by using the language specific PM to install the dependencies I needed for a project.

            Yeah, that’s like mistake #1 for non-FHS-compliant distros. ;)

            • start figuring out how to use guix to emulate FHS inside of a venv

            As the person who implemented a variant of this for Nix (buildFHSEnv), it’s rather straight-forward. Though if it didn’t exist, I’d rather try distrobox or other dev container thingies if there was no reasonable nix support for the thing I’m working on.

            I mean just look at a small part from the beginning of both files: nix formatted by nixfmt

            I mean, that’s just one particular interface. It’s actually quite flexible to do it this way though as it allows you to dumb it down if you don’t like it with a little refactor:

            {
              startup = let
                exec = command: {
                  inherit command;
                };
              in [
                #on launch
                (exec "emacsclient -a '' -nc --init-directory=~/.config/emacs" // {
                  workspace = "1";
                })
                (exec "nitrogen --restore")
                (exec "~/.screenlayout/shareni.sh")
                (exec "numlockx on")
                (exec "volumeicon")
              ];
            }
            

            That’s the beauty of IaC (actual code, not that YAML nonsense): Software environment configuration becomes a software engineering problem and we know how to solve those.

            In this specific case though, I probably wouldn’t bother with doing that stuff in Nix and would rather just keep the plain i3config text file and set the option glue to just use that file; effectively a glorified stow.

            This more complex interface is only truly beneficial if there are parts of your config that vary depending on some other conditions. Some users may have the need to only run a set of commands or have certain launch options on one machine but not another. Trivial to do with lib.optionals and the like using this kind of interface but very hard to do if it was just a list of strings or one large string.

            it fucking added defaults like the keybindings I’ve specifically removed from the config so that the only two i3 deals with are opening the terminal and reloading itself

            Well, then tell it to not to do that? I don’t know the module in question but any well-designed module has an option for precisely that. If it doesn’t, I’d consider that a bug. Otherwise, lib.mkForce is usually also an option.

            Spending a week to configure something simple is worth it in that scenario because it’ll save you from much bigger headaches down the line. The issue is that they solve problems most users simply don’t face, and so the added complexity comes with practically no benefits.

            I wholeheartedly disagree. Declarative stateless system configuration a la Nix solves a lot of issues that users face all the time.

            Whether the time investment is worth it at present is debatable but there’s a clear path towards yes IMO because a project focused around proper IaC elevates operating systems onto another level because it abstracts and centralises configuration. It takes one person to figure out how to configure a certain thing in a sensible way and they can publish that work as a NixOS module for everyone’s benefit. Most of the work I put into NixOS is upstream because of this.

            Right now, it’s absolutely catered towards nerds and other technologically able people like us but imagine what a further abstracted GUI could do for mere mortals.

            • @[email protected]
              link
              fedilink
              19 months ago

              Thanks for the detailed response.

              I’d nowadays be able to solve that particular problem with one line of relatively simple code in NixOS

              I can’t remember the exact details of the whole issue, but that part was for a desktop entry. If I remember correctly, in the end I had to create a system service and there were no readily available examples like for the packages. After days of researching in my spare time, I had to ask in the irc for a snippet from someone’s config.

              As the person who implemented a variant of this for Nix (buildFHSEnv), it’s rather straight-forward.

              Oh, it seems really cool. I’ll need to look into it.

              I mean, that’s just one particular interface. It’s actually quite flexible to do it this way though as it allows you to dumb it down if you don’t like it with a little refactor:

              That’s definitely an improvement, but the default config is still far better IMO.

              I probably wouldn’t bother with doing that stuff in Nix and would rather just keep the plain i3config text file and set the option glue to just use that file; effectively a glorified stow.

              Replacing stow with home-manager has the same issues as replacing a regular distro with nixos. If I can stow all of my dotfiles, why would I use home-manager to handle them instead? In most cases it’s just going to be harder to configure anything, and you also need to rebuild your home every time you want to update a config.

              This more complex interface is only truly beneficial if there are parts of your config that vary depending on some other conditions. Some users may have the need to only run a set of commands or have certain launch options on one machine but not another. Trivial to do with lib.optionals and the like using this kind of interface but very hard to do if it was just a list of strings or one large string.

              What benefits does it have over just using a shell script?

              I guess it’s also great for programs that aren’t following the standards like firefox.

              Well, then tell it to not to do that? I don’t know the module in question but any well-designed module has an option for precisely that. If it doesn’t, I’d consider that a bug.

              It’s probably a skill issue, but that ties into another problem I’ve had when messing around with home-manager: the only source of options I found was mynixos. So to configure anything I had to first guess potential keywords to search for the option I’m interested in. And that’s after learning about it from some video on youtube, because google left me high and dry.

              I wholeheartedly disagree. Declarative stateless system configuration a la Nix solves a lot of issues that users face all the time.

              Can you give me some examples, what issues will I face running MX + nix that I wouldn’t if I ran nixos?

              As someone who works with terraform, I understand the benefits of being forced to keep a single source of truth instead of remembering to update my post-installation script and keep things synced across devices. But on the other hand this is everything I need to do to get a fresh install to where I’m currently at:

              • install the single docker dependency that doesn’t work with home-manager
              • clone my dotfiles and symlink them
              • set up nix, home-manager, and switch
              • remove the few packages I’ve replaced with nix ones
              • cp the i3.desktop (home-manager and sddm were not agreeing)
              • clone and install doom

              It’s definitely not a lot to maintain, and the issues are either obvious and easy to solve, or just a small waste of space. For example if I forget to remove the debian version of git, it’s still going to automatically source the nix one first. Home-manager with just a list of packages makes the hardest part of that process a breeze, while still being really easy to set up.

              The main problem was getting started from 0, so I’m considering writing a post about it when I get a bit more comfortable. Trying to learn nix declarative package management from the nix manual is a bad idea, and almost all of the resources are on nixos. A quickstart guide with a few commands and examples would’ve had me up and running in 10 minutes instead of days.

              Whether the time investment is worth it at present is debatable but there’s a clear path towards yes IMO because a project focused around proper IaC elevates operating systems onto another level because it abstracts and centralises configuration. It takes one person to figure out how to configure a certain thing in a sensible way and they can publish that work as a NixOS module for everyone’s benefit. Most of the work I put into NixOS is upstream because of this.

              Right now, it’s absolutely catered towards nerds and other technologically able people like us but imagine what a further abstracted GUI could do for mere mortals.

              Oh for sure, a home-manager gui that let’s you customize every package from a single place while automatically updating your config would be a complete game changer. But I’m talking about the current state of things. In that regard, currently every linux user can enjoy simple declarative package management with stable and bleeding edge sources. Yet I never see it mentioned, while even beginner threads are being spammed with nixos recommendations. Imagine if casuals could open their software center or discover and install nix packages instead of flatpaks.

              • Atemu
                link
                fedilink
                29 months ago

                If I can stow all of my dotfiles, why would I use home-manager to handle them instead? In most cases it’s just going to be harder to configure anything, and you also need to rebuild your home every time you want to update a config.

                Yes, yes indeed. That’s why my dotfiles are still in a git repo (don’t get the point of stow), not in home-manager.

                If you do in fact need home-manager’s features for some of your dotfiles though, it can effectively act as a stow superset for the rest.

                What benefits does it have over just using a shell script?

                Declarative stateless configuration rather than imperative stateful configuration.

                With a bash script, you’d have to meticulously craft together the i3config file using shell script syntax and remember to run that every time you change something. home-manager just does all of that for you with high-level data types and frameworks specifically made for that purpose.

                that ties into another problem I’ve had when messing around with home-manager: the only source of options I found was mynixos. So to configure anything I had to first guess potential keywords to search for the option I’m interested in.

                Yeah, it’s not great. https://search.nixos.org/options? is really useful for NixOS.

                You have to either use your browser’s dumb search on https://nix-community.github.io/home-manager/options.xhtml or your pager’s dumb search in man home-configuration.nix.

                Can you give me some examples, what issues will I face running MX + nix that I wouldn’t if I ran nixos?

                All the issues which declarative immutable stateless system configuration solves such as atomic updates, configuration rollback in case you messed something up and trivial recovery. I’m sure I’m forgetting some since I’m so used to having them.

                The main problem was getting started from 0, so I’m considering writing a post about it when I get a bit more comfortable. Trying to learn nix declarative package management from the nix manual is a bad idea, and almost all of the resources are on nixos. A quickstart guide with a few commands and examples would’ve had me up and running in 10 minutes instead of days.

                Yeah, docs are a pain point. If you think that section is bad (I think so too), everyone will thank you for rewriting it. Feel free to shoot a PR to Nixpkgs and ping a few people from the docs team if you’re motivated.

                Yet I never see it mentioned, while even beginner threads are being spammed with nixos recommendations.

                I don’t get it either. NixOS is the best thing since sliced bread for a certain kind of person (experienced hacker who has felt the pain points which NixOS relieves) but I’d never recommend it to an inexperienced user in its current state.