I agree with jfb that Nix needs types, but I found it to be a pretty good configuration language as far as it goes. It doesn’t make any really basic design mistakes in syntax or grammar that annoy me every time I use it, and that’s more than I can say for xml, json, or yaml. At the syntactic level it’s roughly on a par with Common Lisp’s version of s-expressions, which is the highest praise I know how to give (for syntax :)). Its binding constructs and its functions are reasonably pleasant to code with, as well.
As a distribution, also, I agree with you - NixOS is very messy in some ways, but I’m happier with it than anything else I’ve tried so far.
I find it somewhat distressing that an Arch user found NixOS too hard to work with. I usually turn to the Arch wiki when I can’t figure out how to do something on NixOS; they are both very manual-transmission distributions, where users can and must do a great many things by hand that would be automated elsewhere. This author is right, though, that packaging new things on Nix is strictly extra work in addition to everything that both NixOS and Arch users have to do.
To the three points of feedback the author gives at the end:
The symlinks are wonderful! Through the decades, most Unix software has accumulated a great many environmental dependencies that no human would be able to enumerate. It’s only by breaking the legacy mechanisms, and having to replace them with explicit ones, that we can get to a better situation.
“Do one thing and do it well” is hard to argue for or against, as it’s a question of personal goals and vision, but fortunately the author only gives one concrete example - per-user mutable environments - and I’m not sure there are others, so I’ll only address that. :) Given how much heavy lifting Nix has to do to make its core strategy work, I see this feature as easy in comparison and not a big deal. Personally, though, I don’t use it and share this author’s desire to have a way to turn it off altogether.
With regard to trying to hide transitive runtime dependencies, I strongly support what Nix is trying to do, and disagree with this author. It’s not at all difficult for transitive dependencies to include 90% of the system (try building Chromium from source sometime). At that point, you no longer have any idea what your direct dependencies really are; as things evolve, you will absolutely depend on things you haven’t declared. Then things will change elsewhere and your package will break, which is not fun to diagnose; it’s far more sustainable for packagers to do that work up front.
I like NixOS, but I don’t like Nix-the-language (it badly needs types), and I wish there were a more elegant implementation solution than an impenetrable blizzard of symlinks. Still, I like it significantly more than any other Linux distribution I’ve used, and I trust their model for system configuration. But yeah, types.
Perhaps the symlinks in ~/.nix-profile? I’m not sure though because while there may be a lot, you don’t normally care what they are or where they point when you’re using nix-env/shell etc…
It’s more regretting that symlinks are the tool for delivering the necessary abstraction layers. Something that works more like union mounts and Plan 9 namespacing would be more elegant.
Sure. But the order of my interest in Nix* stuff is NixOS > Nix-the-package-manager > Nix-the-language. I would be much happier with sacrifices to the portability of the latter two to improve the experience on the former.
Making nix the package manager unportable means you’re basically telling existing users of nix on linux (not nixos), solaris, and OS X that their experiences should be not to use nix.
I’m not sure that is a good way to sell people on nix as a concept. But you’re free to propose it as an issue. Just realize that basically it would mean I’d ditch nixos as a linux os too. I don’t really like the idea of abandoning portability just to make things elegant.
Oh, I’m a realist. NixOS is actually good enough to use, and, as my old boss at Apple used to say, the world would go broke if it were built to my preferences. I’m just trying to explain what a More Perfect System would look like to me.
I have to disagree that union mounts are more elegant.
How do you find out when a union mount has happened? How do you find out what all the layers are? The CLI mount tool’s description of the situation is absolutely unreadable; in fact, on systems that use union mounts, I generally find that I can’t even identify my normal mounts unless I already know the device names to grep for.
If something has manually unmounted something that needed to be there, how do you find out which one it was and put it back? All I can think of is to reboot.
Symlinks, at least I know how I can inspect any individual one, and there’s a clearly documented API if I need to consume them in any more interesting way. And they aren’t nearly as likely to be accidentally modified.
It does not surprise me in the least that union mounts in the real world are crap. But the idea, unfettered by the cold dead hand of backwards compatibility, has always struck me as Right in a way that horrors like PATH or forests of symlinks cannot.
Nix is the one thing I miss from Linux on FreeBSD. Every now and then I get the courage to try to get Nix working on FreeBSD but, unfortunately, for such an elegant idea the code is absolute trash. Full of ifdef’s and Linuxisms and held together by shoestring.
This somewhat mirrors my own experience with NixOS. I tried it for about a
month because I liked the ideas behind it. But I eventually went back to my
previous Linux distribution after discovering too many rough edges:
While you can install multiple versions of a package in parallel you might not
be able to run them in parallel. For example GnuPG automatically launches
gpg-agent, which listens on a socket at a default location. gpg2 won’t
communicate with gpg-agent from a different version and therefore refuse to
work.
NixOS’s packaging should make reproducibility easy. However I encountered
quite a lot of broken packages in their repositories.
NixOS comes with its own configuration management system. Unfortunately it’s
not very flexible. If an option for you what you want doesn’t already exist
you have to fork the source repository and add it there. For example I
haven’t found a way to add a custom line to a PAM configuration file generated
by NixOS.
The documentation is quite lacking. A lot of functionality is implemented in
some Nix Expression libraries, for which the is no documentation at all. I
was unable to create a package which needed FHSUserEnv, since I couldn’t
figure out how to use it properly.
In the end it was too much effort to get my home workstation to do what I wanted
it to with NixOS. I decided to stick with Arch Linux, Ansible and ZFS, which i
find more predictable, better documented and easier to work with for my use
case.
I agree with jfb that Nix needs types, but I found it to be a pretty good configuration language as far as it goes. It doesn’t make any really basic design mistakes in syntax or grammar that annoy me every time I use it, and that’s more than I can say for xml, json, or yaml. At the syntactic level it’s roughly on a par with Common Lisp’s version of s-expressions, which is the highest praise I know how to give (for syntax :)). Its binding constructs and its functions are reasonably pleasant to code with, as well.
As a distribution, also, I agree with you - NixOS is very messy in some ways, but I’m happier with it than anything else I’ve tried so far.
I find it somewhat distressing that an Arch user found NixOS too hard to work with. I usually turn to the Arch wiki when I can’t figure out how to do something on NixOS; they are both very manual-transmission distributions, where users can and must do a great many things by hand that would be automated elsewhere. This author is right, though, that packaging new things on Nix is strictly extra work in addition to everything that both NixOS and Arch users have to do.
To the three points of feedback the author gives at the end:
The symlinks are wonderful! Through the decades, most Unix software has accumulated a great many environmental dependencies that no human would be able to enumerate. It’s only by breaking the legacy mechanisms, and having to replace them with explicit ones, that we can get to a better situation.
“Do one thing and do it well” is hard to argue for or against, as it’s a question of personal goals and vision, but fortunately the author only gives one concrete example - per-user mutable environments - and I’m not sure there are others, so I’ll only address that. :) Given how much heavy lifting Nix has to do to make its core strategy work, I see this feature as easy in comparison and not a big deal. Personally, though, I don’t use it and share this author’s desire to have a way to turn it off altogether.
With regard to trying to hide transitive runtime dependencies, I strongly support what Nix is trying to do, and disagree with this author. It’s not at all difficult for transitive dependencies to include 90% of the system (try building Chromium from source sometime). At that point, you no longer have any idea what your direct dependencies really are; as things evolve, you will absolutely depend on things you haven’t declared. Then things will change elsewhere and your package will break, which is not fun to diagnose; it’s far more sustainable for packagers to do that work up front.
The Arch wiki is fabulous, however, a wonderful resource even for those of us who don’t use Arch.
I like NixOS, but I don’t like Nix-the-language (it badly needs types), and I wish there were a more elegant implementation solution than an impenetrable blizzard of symlinks. Still, I like it significantly more than any other Linux distribution I’ve used, and I trust their model for system configuration. But yeah, types.
How does it compare to the scheme that GuixSD uses?
I’ve been using NixOS for a few years. I absolutely agree.
What does this mean?
I believe it refers to everything under /nix/store.
Yes, some things in /nix/store are symlinks, not everything. What is an “impenetrable blizzard of symlinks” though?
Perhaps the symlinks in ~/.nix-profile? I’m not sure though because while there may be a lot, you don’t normally care what they are or where they point when you’re using nix-env/shell etc…
It’s more regretting that symlinks are the tool for delivering the necessary abstraction layers. Something that works more like union mounts and Plan 9 namespacing would be more elegant.
Also a lot less portable. Nix the package manager runs on more than just nixos/linux.
Sure. But the order of my interest in Nix* stuff is NixOS > Nix-the-package-manager > Nix-the-language. I would be much happier with sacrifices to the portability of the latter two to improve the experience on the former.
Making nix the package manager unportable means you’re basically telling existing users of nix on linux (not nixos), solaris, and OS X that their experiences should be not to use nix.
I’m not sure that is a good way to sell people on nix as a concept. But you’re free to propose it as an issue. Just realize that basically it would mean I’d ditch nixos as a linux os too. I don’t really like the idea of abandoning portability just to make things elegant.
Oh, I’m a realist. NixOS is actually good enough to use, and, as my old boss at Apple used to say, the world would go broke if it were built to my preferences. I’m just trying to explain what a More Perfect System would look like to me.
I have to disagree that union mounts are more elegant.
How do you find out when a union mount has happened? How do you find out what all the layers are? The CLI mount tool’s description of the situation is absolutely unreadable; in fact, on systems that use union mounts, I generally find that I can’t even identify my normal mounts unless I already know the device names to grep for.
If something has manually unmounted something that needed to be there, how do you find out which one it was and put it back? All I can think of is to reboot.
Symlinks, at least I know how I can inspect any individual one, and there’s a clearly documented API if I need to consume them in any more interesting way. And they aren’t nearly as likely to be accidentally modified.
It does not surprise me in the least that union mounts in the real world are crap. But the idea, unfettered by the cold dead hand of backwards compatibility, has always struck me as Right in a way that horrors like PATH or forests of symlinks cannot.
This is a fair position. :)
Nix is the one thing I miss from Linux on FreeBSD. Every now and then I get the courage to try to get Nix working on FreeBSD but, unfortunately, for such an elegant idea the code is absolute trash. Full of
ifdef
’s and Linuxisms and held together by shoestring.Next version will have no Perl, dunno if that helps.
This somewhat mirrors my own experience with NixOS. I tried it for about a month because I liked the ideas behind it. But I eventually went back to my previous Linux distribution after discovering too many rough edges:
gpg-agent
, which listens on a socket at a default location.gpg2
won’t communicate withgpg-agent
from a different version and therefore refuse to work.FHSUserEnv
, since I couldn’t figure out how to use it properly.In the end it was too much effort to get my home workstation to do what I wanted it to with NixOS. I decided to stick with Arch Linux, Ansible and ZFS, which i find more predictable, better documented and easier to work with for my use case.
Often the packages are reproducibly broken.
I’ve been able to build big FHS environments using something like:
https://github.com/puffnfresh/nix-files/blob/master/fhs-tar.nix