Personally, I think the Debian model of having a free core but allowing a non-free area is better for building a community and thus a distribution. Actively restricting conversation in official channels about non-free software and hardware(!) is user hostile. Being a purist may make you feel self-righteous, but very few people in this world can afford such luxuries and will just move on.
Honestly, the guix model is very similar to Debian. There is no nonfree allowed in “official” channels, but everyone in the “official” channels knows about #nonguix which is the equivalent of Debian nonfree.
The culture is very different. People on the Guix subreddit get attacked when they mention nonguix. I was curious about Guix, so I googled how to install proprietary Nvidia drivers, which I need for work. Not only are they not supported, Guix users get angry when people try to help others install them on even non-official forums like Reddit.
ehhhh. The GNU community is rather hostile to non-free software overall. I mean, what do you expect, it’s an organization dedicated to a software that intentionally makes it hard to use with non-free software (GPL).
This also got posted to HN, there’s a noteworthy discussion on some security concerns wrt. Linux-libre:
Guix System is an advanced distribution of the GNU operating system. It uses the Linux-libre kernel
It’s worth pointing out that the linux-libre kernel is developed under the FSF doctrine that “binary blobs are bad unless you can’t see them”. This has been taken to its logical extreme here, where this Linux fork actively removes security warnings informing users that they need to update their CPU microcode, because microcode in ROM is fine but dynamically loaded microcode updates are not, in this school of thought.
I have no interest in software that uses arbitrary religious dogma (that doesn’t help users’ freedom, as those users’ CPUs have proprietary microcode whether they know about it or not) to justify censoring critical security vulnerability notifications for users. I regard this as actively evil anti-user behavior.
I’m a Guix user, and acknowledge that linux-libre’s microcode security/freedom decision is not what I’d pick. Many Guix users choose to use the vanilla kernel from https://gitlab.com/nonguix/nonguix#CPU%20Microcode for similar reasons.
However, it’s not surprising that software freedom groups value freedom and will sacrifice security for it. That’s the nature of prioritizing values: some other important values will be second place.
Values aren’t prioritized for no reason, however. Picking freedom over security in this way might have some positive effects (as well as the obvious negative effects):
microcode updates could downgrade the experience in ways the user doesn’t agree to.
it might encourage Intel to open their microcode specs/updates. This sounds far fetched, but we’ve seen large openness wins in the WiFi and GPU space over the past few years.
it might encourage users to purchase hardware that has open microcode updates.
FWIW, I prefer free software, but am willing to sacrifice it for security at times.
That’s a weird position for the guix though because you still run the microcode, you still get partial updates for it (bios), and they spent time to hide warnings. Trying to hide the fact you have the freedom to get the updates, because their idea of freedom doesn’t like the updates is serious mental gymnastics.
I agree. I see this as a too large a security compromise for such a small win of “Freedom”.
That said, drawing these lines makes it really clear what FSF/free software movement’s priorities are, which is important for public sentiment/recognition/visibility.
When I think of FSF/free software movement I think “their goals align with mine, but I don’t always agree with their methods”. That’s a decent position for an advocacy group/movement.
It doesn’t really matter the minutiae of the decision. Once these people have decided they know better than you what you should be allowed to know because they want to guide your behaviour for their religious crusade, they are not to be trusted with your OS.
Early on Nix had the opposite problem. You would ask it to install firefox, and completely unprompted it would install the adobe flash plugin to go with it. They told me if I wanted firefox without that awful shit to install a separate “firefox-no-plugins” package or something ridiculous like that.
It hasn’t done that for a while, but it’s taken like a decade to recover from the lost trust. I couldn’t handle the idea of running an OS managed by people capable of making such a spectacularly bad decision.
Doesn’t that depend on your affinities? If you like lisp languages then Guix seems like a logical choice. I guess it also depends on what software you depend on in your day-to-day activities.
Guix is a GNU project with the unique lenses and preferences that come along with that. It is also a much smaller community that Nix, which means less packages, less eyes on the software, and I would argue also less diversity of thought.
I personally prefer Scheme to Nix’s DSL-ish language, but as a project I think Nix is in a much better position to deliver a reasonable system of such levels of ambition.
It also frustrates me that Guix tries to act like it’s not just a fork of Nix, when in reality it is, and it would be better to embrace this and try to collaborate and follow Nix more closely.
Unfortunately the GNU dogma probably plays a role in preventing that.
It is also a much smaller community that Nix, which means less packages
If you convert Nix packages to Guix packages, you can get the best of both worlds in Guix. But that’s admittedly not a very straightforward process, and guix-import is being/has been removed due to bugginess.
I’m aware of both, but I tried Guix first because people I know use it, I like the idea of using a complete programming language (even if I dislike parens), and the importers made getting started easy. Also guix is just an apt install away for me.
I’m migrating from NixOS to Guix System at the moment.
NixOS is great, but after 4 years, I’ve had difficulties understanding some of Nix’s foundations:
I don’t write intermediate Nix often enough for it to be a smooth process.
I have difficulty remembering/tracking use of nixpkgs’s lib/ and nixos/lib directories.
I cannot easily determine what the Nix tooling does. I’m not strong in C++.
Guix fixes those foundational issues:
Guile was easy for me to pickup.
Guile has language-level modules/imports, and good libraries/editor support, making it easier to understand the relevant libraries.
Guix’s tooling is written in Guile
Guix has issues, but they are more easily fixable:
Fewer packages than NixOS. Guix has most of the packages I care about. I can contribute the rest.
Strict focus on free software. I support free software, but would like support for non-free software at times too. I’m happy to use nonguix. This approach worked well enough for me when I used Debian nonfree in the past.
NixOS and Guix System are both great choices, IMO.
I’m getting more and more interested in Guix (and Nix) as they keep getting brought up around here quite often nowadays. The first post I read was packaging pytorch for Guix (lobsters discussion), which turns out to be astonishingly complex. Since I only recently set up my new PC I don’t think I’ll switch anytime soon (mostly because I don’t want to deal with yet another package manager), but possibly for the next time I’m going to install a distro I’ll keep it in mind and try to evaluate the project.
It feels to me that the major feature is rollbacks. Now while I can understand that, after all it’s why people like having backups and ZFS snapshots (and but environments by extension) I just don’t really see how this really matters being integrated into the package manager really matters. If you have software installing it uninstalling software seems to have worked fine over the past few decades.
Is state/data/configuration somehow managed in a special way?
When I think of such scenarios the burden is on getting stuff that is not managed by package managers back into order.
On the topic of running multiple versions. While I very rarely have wanted to do that, mostly for Debugging or bad upgrade paths of software while not having backups from the article I understand that certain services are being run multiple times with different versions. If that is correct I’m very curious how that is done in relation to sockets (Unix, TCP, etc ) how does other software decide where to connect to? Just the address or is there something else in how packages are built handled that helps with deciding?
It feels to me that the major feature is rollbacks.
I’m a keen NixOS and Guix user, and I don’t consider this to be directly important, though I can see why it’s seen that way.
On the topic of running multiple versions.
I also don’t run multiple versions of things.
The biggest benefit that NixOS/Guix introduces for me is that I can treat my machine as code, with high fidelity and efficiently.
In Linux distributions such as Debian/Arch/CentOS, I consider my machine to be a 30GB mutable blob (the contents of /etc, /usr, etc.). Updates are mutations to this 30GB blob, and I have low confidence how it’s going to behave. Cfgmgmt /automates/ this, automating low-confidence steps still results in low confidence.
For NixOS/Guix, I consider my machine to be about 100kB (my Guix config). I can understand this 100kB, and when I change the system, I change this 100kB, and accurately know what state my machine will in after its changed: the update is actually a replace.
Is state/data/configuration somehow managed in a special way?
~Everything in /etc is managed via NixOS/Guix.
~nothing in /var/ is managed via NixOS/Guix. NixOS/Guix reduces my state space, but /var is still state I have to care about. (Actually, on my desktop no state is preserved on /var between boots: every boot has a fresh computer smell.)
Hey, thanks a lot for your response. I have some naive questions then.
In your desktop system, in many cases that blob, the state one cares about would probably be in $HOME. What about that?
What do you mean sheet “/etc is managed”? Say I have a configuration that would usually lie there. Where is it now? Say I want to customize it what would I do? Say configuration syntax changes, what would I do?
I understand your comparison with mutable blob vs declared state, after all that’s the same approach that other kinds of software often use, be it configuration management, some cloud/service orchestration tools and honestly a lot of software that has the word declarative in the first few sentences.
In practical use I see these systems fall apart very quickly, because a lot of the time it’s more a changing state in the way one would define a sweet of database migrations.
So for a simple example. Let’s take /etc. That’s the configuration. You in many situations can copy that to a new system and it’s fresh and the way you want. Various package managers also can output a list of which packages are installed in a format that can be read so you usually have /usr covered as well. Because of that I don’t usually see this part as a big issue. After all that’s in a way how many distro installers look at things. /boot is similar. /usr should not be touched, though sometimes it can be an emergency hack, but I prefer to have it read only other than on changes by the package manager.
That leaves /var and /home, which sounds at least somewhat similar to what you are saying (correct me if I’m wrong. So in my understanding what is done is more that the system makes sure that what should be actually is? Talking about upgrades, removals, etc. not leaving stuff behind? I guess that makes quick hacks hard or impossible? Don’t get me wrong I’d actually consider that a good thing.
/var on desktop might not have much needed state, but in many situations that state would be in /home.
Anyways, thank you again for your response. I guess at this point it might make sense if I took a closer look at it myself. I just am curious about practical experiences, because I completely understand that declaratively describing a system tends to look very nice on paper, but in many situations (also because of badly designed software) is more like simply writing a setup shell script and maybe running it each boot, just that shell scripts tend to be more flexible for better and for worse.
Of course having a solution that does that fit you with a good abstraction is interesting.
That’s why lately I’ve been thinking about where we handle big blobs that we sometimes want to modify in a predictive manner and had to think about database schemas and migrations.
What do you mean sheet “/etc is managed”? Say I have a configuration that would usually lie there. Where is it now? Say I want to customize it what would I do? Say configuration syntax changes, what would I do?
The contents live as part of your nix configuration. It’s both awesome and frustrating at times. Nix tries to overlay it’s view of reality onto the config file format, so say it’s nginx and instead of trying to write nginx confg like:
http {
sendfile on;
}
in nix you would write something like:
services.nginx.http.sendfile = true;
and then when nix goes to build the system, it will generate a nginx config file for you. This allows for some nice things, like services.nginx.recommendedOptimisation = true; and it will fill in a lot of boilerplate for you.
Not all of nix is this integrated with the config file(s), so sometimes you get some oddities, or sometimes the magic that nix adds isn’t very clear and you have to go dig around to see what it’s actually doing.
Another downside, is it means a re-build every time you want to change a minor thing in 1 application. The upside, nix is usually really good about not restarting the entire world and will try to just restart that 1 application that changed. This is just an off-shoot of the declarative process, and some will call it a feature, especially in production, but it can be annoying when in development.
You can turn all of that off and just say this app will read from /var/etc/nginx/nginx.conf and leave nginx.conf entirely in your control. This is handy when moving to nix, or maybe in development of a new service or something.
As far as the mutable state of applications, nix mostly punts on this, and makes it YOUR problem. There is some nix config options that packagers of apps can take advantage of, so say on upgrades, if you installed PG11 originally, it won’t willy nilly upgrade you to PG12. It makes you do that yourself. So you get all the new bits except PG11 will still run.
All that said this stuff isn’t perfect, so testing is your friend.
You can turn all of that off and just say this app will read from /var/etc/nginx/nginx.conf and leave nginx.conf entirely in your control.
My goodness, do you have a guide or blogpost or something for this way of going about it? That’d be super helpful. I’ve tried Nix a few times and this is exactly where I go crazy. I can store real config files in git too; just let me do that! (and avoid the Nix language!)
If a module doesn’t meet my needs, and I can’t easily make it do so, sometimes I will write my own module, to have fully control over it. I still reuse the nginx package, and would typically start my module by copy-pasting and trimming the existing one.
95% of the time, the provided modules do exactly what I want.
Well, doing this in some ways defeats one of the big reasons for Nix, but there are valid use-cases:
For nginx, this is what I do:
# this sets the config file to /etc/nginx/nginx.conf, perfect for us using consul-template.
services.nginx.enableReload = true;
services.nginx.config = "#this should be replaced.";
Now it’s on you to maintain /etc/nginx/nginx.conf
For us, we use consul-template(ran via systemd as more nix configuration) and it generates the config. But you are free to replace it (after deploy) manually. i.e. nix will over-write the /etc/nginx/nginx.conf file every nixos-rebuild build with the contents: #this should be replaced.
Otherwise, what nixos tends to do is symlink the /etc//configfile -> to somewhere in /nix which is read-only for you. so it’s up to you to erase the symlink and put a real file there. One could automate this with a systemd service that runs on startup.
Another way to do this, is hack up the systemd service, assuming the service will accept the location of the config file as a cmd line argument. This is non-standard and can be fiddly in nix.
On Guix system it is recommended to manage anything in etc via a “service” which will be written/configuerd in scheme and has deploy and rollback semantics.
For config that lives in $HOME there is guix home and guix home services, which parallel the system for /etc and system services, and even work on other operating systems.
In your desktop system, in many cases that blob, the state one cares about would probably be in $HOME. What about that?
I use https://github.com/nix-community/home-manager to manage $HOME. I use that to manage my git config and bashrc. I also use it to declare which directories should survive a reboot. e.g. I persist ~/.steam and ~/.thunderbird, “Documents/”, a few others. But everything else, e.g. ~/.vim (which I only use in an ad-hoc manner) is wiped.
Even that leaves some blob-like state: I persist “.config/dconf”. Ideally that could be managed declaratively, but I haven’t seen a workable solution.
Let’s take /etc. That’s the configuration. You in many situations can copy that to a new system and it’s fresh and the way you want. Various package managers also can output a list of which packages are installed in a format that can be read so you usually have /usr covered as well.
That works fine for building new machines well, but a typical Linux machine is built far less frequently than its updated. For example, I’ve managed machines with packages/Puppet/Ansible in the past, and occasionally run into situations where the machine state according to packages/Puppet/Ansible no longer matches the actual machine state:
postinst scripts that worked well during install, but get updated such that upgrades work and installs are broken.
cases where apt-get install $x followed by apt-get purge $x leaves live config (e.g. files in /etc/pam.d)
cases where the underlying packages are changed in ways incompatible with the Puppet config: after all, the underlying packages typically don’t attempt to QA against Puppet config.
The result is that even just covering /etc and /usr, machines are brittle, and occasionally need to be rebuilt to have confidence.
Talking about upgrades, removals, etc. not leaving stuff behind? I guess that makes quick hacks hard or impossible? Don’t get me wrong I’d actually consider that a good thing.
Yes, it does make quick hacks hard/impossible. It is possible to do some quick hacks on the box (systemctl stop foo, for example), and nixpkgs is designed so that various parts can be overridden if needed.
When we climb the ladder of abstraction, and lose access to easily change the inner workings of lower levels, it looks like (and is!) restrictive. In the same way I wouldn’t modify a binary in a hex editor to perform deployments, nor would I make live changes to a Docker image, I aim to not SSH to a machine to mutate it either. I prefer my interactions with lower-level abstractions to be mediated via tooling that applies checks-and-balances.
Anyways, thank you again for your response. I guess at this point it might make sense if I took a closer look at it myself.
I don’t make recommendations without understanding requirements, but NixOS/Guix is at least a novel approach to distributions, which might be interesting to OS folks.
NixOS/Guix might have come too late for industry: containers also aim to manage system complexity, and do a good job of it. I think NixOS/Guix offers good solutions for low-medium scale, and as a way to build container images.
I just am curious about practical experiences, because I completely understand that declaratively describing a system tends to look very nice on paper, but in many situations (also because of badly designed software) is more like simply writing a setup shell script and maybe running it each boot, just that shell scripts tend to be more flexible for better and for worse.
I only use NixOS/Guix for my personal infra, and manage all those machines in a declarative manner (other than out-of-scope things such as databases like ~/.config/dconf and postgres).
That’s why lately I’ve been thinking about where we handle big blobs that we sometimes want to modify in a predictive manner and had to think about database schemas and migrations.
Yes, DB schema migrations is an interesting case where a declarative approach would be nice to have: it’s much easier to reason about a single SQL DDL than a sequence of updates.
A similar problem I have is the desire for declarative disk partitions: ideally I could declare my partition scheme, and apply a diff-patch of mutations to make the declaration reality. It would only proceed if it was safe and preserved the underlying files. It’d likely only be possible under particular constraints (lvm/btrfs/zfs ?). Even then that’s hard to get right!
Personally, I think the Debian model of having a free core but allowing a non-free area is better for building a community and thus a distribution. Actively restricting conversation in official channels about non-free software and hardware(!) is user hostile. Being a purist may make you feel self-righteous, but very few people in this world can afford such luxuries and will just move on.
Honestly, the guix model is very similar to Debian. There is no nonfree allowed in “official” channels, but everyone in the “official” channels knows about #nonguix which is the equivalent of Debian nonfree.
The culture is very different. People on the Guix subreddit get attacked when they mention nonguix. I was curious about Guix, so I googled how to install proprietary Nvidia drivers, which I need for work. Not only are they not supported, Guix users get angry when people try to help others install them on even non-official forums like Reddit.
On a subreddit? That’s just weirdly hypocritical…
I mostly hang out in the IRC
Meanwhile on Arch
ehhhh. The GNU community is rather hostile to non-free software overall. I mean, what do you expect, it’s an organization dedicated to a software that intentionally makes it hard to use with non-free software (GPL).
This also got posted to HN, there’s a noteworthy discussion on some security concerns wrt. Linux-libre:
I’m a Guix user, and acknowledge that linux-libre’s microcode security/freedom decision is not what I’d pick. Many Guix users choose to use the vanilla kernel from https://gitlab.com/nonguix/nonguix#CPU%20Microcode for similar reasons.
However, it’s not surprising that software freedom groups value freedom and will sacrifice security for it. That’s the nature of prioritizing values: some other important values will be second place.
Values aren’t prioritized for no reason, however. Picking freedom over security in this way might have some positive effects (as well as the obvious negative effects):
FWIW, I prefer free software, but am willing to sacrifice it for security at times.
That’s a weird position for the guix though because you still run the microcode, you still get partial updates for it (bios), and they spent time to hide warnings. Trying to hide the fact you have the freedom to get the updates, because their idea of freedom doesn’t like the updates is serious mental gymnastics.
I agree. I see this as a too large a security compromise for such a small win of “Freedom”.
That said, drawing these lines makes it really clear what FSF/free software movement’s priorities are, which is important for public sentiment/recognition/visibility.
When I think of FSF/free software movement I think “their goals align with mine, but I don’t always agree with their methods”. That’s a decent position for an advocacy group/movement.
It doesn’t really matter the minutiae of the decision. Once these people have decided they know better than you what you should be allowed to know because they want to guide your behaviour for their religious crusade, they are not to be trusted with your OS.
We have? I thought free+open WiFi ended with the 802.11n Atheros chipset, and Nvidia is as closed as ever.
NVIDIA is closed, but both AMD and Intel are doing pretty well with upstream Linux drivers as far as I know.
I don’t understand why one would use Guix without trying Nix first.
What I gathered is that the author has a preference for Scheme and thus also for Guix, which I think is a sufficient argument.
However, I’d be very interested in reading an in-depth comparison between the two projects, as they target the same niche and are quite related.
This is basically my position. I’ve used Nix a couple times but Guix is preferable.
Early on Nix had the opposite problem. You would ask it to install firefox, and completely unprompted it would install the adobe flash plugin to go with it. They told me if I wanted firefox without that awful shit to install a separate “firefox-no-plugins” package or something ridiculous like that.
It hasn’t done that for a while, but it’s taken like a decade to recover from the lost trust. I couldn’t handle the idea of running an OS managed by people capable of making such a spectacularly bad decision.
Doesn’t that depend on your affinities? If you like lisp languages then Guix seems like a logical choice. I guess it also depends on what software you depend on in your day-to-day activities.
There is more to consider here:
Guix is a GNU project with the unique lenses and preferences that come along with that. It is also a much smaller community that Nix, which means less packages, less eyes on the software, and I would argue also less diversity of thought.
I personally prefer Scheme to Nix’s DSL-ish language, but as a project I think Nix is in a much better position to deliver a reasonable system of such levels of ambition.
It also frustrates me that Guix tries to act like it’s not just a fork of Nix, when in reality it is, and it would be better to embrace this and try to collaborate and follow Nix more closely.
Unfortunately the GNU dogma probably plays a role in preventing that.
If you convert Nix packages to Guix packages, you can get the best of both worlds in Guix. But that’s admittedly not a very straightforward process, and
guix-import
is being/has been removed due to bugginess.I’m aware of both, but I tried Guix first because people I know use it, I like the idea of using a complete programming language (even if I dislike parens), and the importers made getting started easy. Also guix is just an apt install away for me.
+1 to all this.
I’m migrating from NixOS to Guix System at the moment.
NixOS is great, but after 4 years, I’ve had difficulties understanding some of Nix’s foundations:
Guix fixes those foundational issues:
Guix has issues, but they are more easily fixable:
NixOS and Guix System are both great choices, IMO.
I’m getting more and more interested in Guix (and Nix) as they keep getting brought up around here quite often nowadays. The first post I read was packaging pytorch for Guix (lobsters discussion), which turns out to be astonishingly complex. Since I only recently set up my new PC I don’t think I’ll switch anytime soon (mostly because I don’t want to deal with yet another package manager), but possibly for the next time I’m going to install a distro I’ll keep it in mind and try to evaluate the project.
Discussion for this on HN.
I clicked through to the Speck system since I haven’t heard of it before. Its package description looks so much more sane than nix’s: https://spack-tutorial.readthedocs.io/en/latest/tutorial_packaging.html#id7
I wonder if we can have some nicer “compiles to nix” alternatives in the future.
You don’t need to change your OS to try nix or guix. They can be installed on other OSes.
It feels to me that the major feature is rollbacks. Now while I can understand that, after all it’s why people like having backups and ZFS snapshots (and but environments by extension) I just don’t really see how this really matters being integrated into the package manager really matters. If you have software installing it uninstalling software seems to have worked fine over the past few decades.
Is state/data/configuration somehow managed in a special way?
When I think of such scenarios the burden is on getting stuff that is not managed by package managers back into order.
On the topic of running multiple versions. While I very rarely have wanted to do that, mostly for Debugging or bad upgrade paths of software while not having backups from the article I understand that certain services are being run multiple times with different versions. If that is correct I’m very curious how that is done in relation to sockets (Unix, TCP, etc ) how does other software decide where to connect to? Just the address or is there something else in how packages are built handled that helps with deciding?
I’m a keen NixOS and Guix user, and I don’t consider this to be directly important, though I can see why it’s seen that way.
I also don’t run multiple versions of things.
The biggest benefit that NixOS/Guix introduces for me is that I can treat my machine as code, with high fidelity and efficiently.
In Linux distributions such as Debian/Arch/CentOS, I consider my machine to be a 30GB mutable blob (the contents of /etc, /usr, etc.). Updates are mutations to this 30GB blob, and I have low confidence how it’s going to behave. Cfgmgmt /automates/ this, automating low-confidence steps still results in low confidence.
For NixOS/Guix, I consider my machine to be about 100kB (my Guix config). I can understand this 100kB, and when I change the system, I change this 100kB, and accurately know what state my machine will in after its changed: the update is actually a replace.
~Everything in /etc is managed via NixOS/Guix.
~nothing in /var/ is managed via NixOS/Guix. NixOS/Guix reduces my state space, but /var is still state I have to care about. (Actually, on my desktop no state is preserved on /var between boots: every boot has a fresh computer smell.)
Hey, thanks a lot for your response. I have some naive questions then.
In your desktop system, in many cases that blob, the state one cares about would probably be in $HOME. What about that?
What do you mean sheet “/etc is managed”? Say I have a configuration that would usually lie there. Where is it now? Say I want to customize it what would I do? Say configuration syntax changes, what would I do?
I understand your comparison with mutable blob vs declared state, after all that’s the same approach that other kinds of software often use, be it configuration management, some cloud/service orchestration tools and honestly a lot of software that has the word declarative in the first few sentences.
In practical use I see these systems fall apart very quickly, because a lot of the time it’s more a changing state in the way one would define a sweet of database migrations.
So for a simple example. Let’s take /etc. That’s the configuration. You in many situations can copy that to a new system and it’s fresh and the way you want. Various package managers also can output a list of which packages are installed in a format that can be read so you usually have /usr covered as well. Because of that I don’t usually see this part as a big issue. After all that’s in a way how many distro installers look at things. /boot is similar. /usr should not be touched, though sometimes it can be an emergency hack, but I prefer to have it read only other than on changes by the package manager.
That leaves /var and /home, which sounds at least somewhat similar to what you are saying (correct me if I’m wrong. So in my understanding what is done is more that the system makes sure that what should be actually is? Talking about upgrades, removals, etc. not leaving stuff behind? I guess that makes quick hacks hard or impossible? Don’t get me wrong I’d actually consider that a good thing.
/var on desktop might not have much needed state, but in many situations that state would be in /home.
Anyways, thank you again for your response. I guess at this point it might make sense if I took a closer look at it myself. I just am curious about practical experiences, because I completely understand that declaratively describing a system tends to look very nice on paper, but in many situations (also because of badly designed software) is more like simply writing a setup shell script and maybe running it each boot, just that shell scripts tend to be more flexible for better and for worse.
Of course having a solution that does that fit you with a good abstraction is interesting.
That’s why lately I’ve been thinking about where we handle big blobs that we sometimes want to modify in a predictive manner and had to think about database schemas and migrations.
Thanks again, have a nice day. :)
The contents live as part of your nix configuration. It’s both awesome and frustrating at times. Nix tries to overlay it’s view of reality onto the config file format, so say it’s nginx and instead of trying to write nginx confg like:
in nix you would write something like:
and then when nix goes to build the system, it will generate a nginx config file for you. This allows for some nice things, like services.nginx.recommendedOptimisation = true; and it will fill in a lot of boilerplate for you.
Not all of nix is this integrated with the config file(s), so sometimes you get some oddities, or sometimes the magic that nix adds isn’t very clear and you have to go dig around to see what it’s actually doing.
Another downside, is it means a re-build every time you want to change a minor thing in 1 application. The upside, nix is usually really good about not restarting the entire world and will try to just restart that 1 application that changed. This is just an off-shoot of the declarative process, and some will call it a feature, especially in production, but it can be annoying when in development.
You can turn all of that off and just say this app will read from /var/etc/nginx/nginx.conf and leave nginx.conf entirely in your control. This is handy when moving to nix, or maybe in development of a new service or something.
As far as the mutable state of applications, nix mostly punts on this, and makes it YOUR problem. There is some nix config options that packagers of apps can take advantage of, so say on upgrades, if you installed PG11 originally, it won’t willy nilly upgrade you to PG12. It makes you do that yourself. So you get all the new bits except PG11 will still run.
All that said this stuff isn’t perfect, so testing is your friend.
My goodness, do you have a guide or blogpost or something for this way of going about it? That’d be super helpful. I’ve tried Nix a few times and this is exactly where I go crazy. I can store real config files in git too; just let me do that! (and avoid the Nix language!)
https://search.nixos.org/options?channel=21.05&from=0&size=50&sort=relevance&type=packages&query=services.nginx is where I’d start to look for how to disable the config management part of the nginx service. If that wasn’t enough, I’d go to the corresponding file in nixpkgs.
If a module doesn’t meet my needs, and I can’t easily make it do so, sometimes I will write my own module, to have fully control over it. I still reuse the nginx package, and would typically start my module by copy-pasting and trimming the existing one.
95% of the time, the provided modules do exactly what I want.
https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md aims to make the “please let me take control over the service” usecase easier.
Well, doing this in some ways defeats one of the big reasons for Nix, but there are valid use-cases:
For nginx, this is what I do:
Now it’s on you to maintain /etc/nginx/nginx.conf
For us, we use consul-template(ran via systemd as more nix configuration) and it generates the config. But you are free to replace it (after deploy) manually. i.e. nix will over-write the /etc/nginx/nginx.conf file every
nixos-rebuild build
with the contents:#this should be replaced.
Otherwise, what nixos tends to do is symlink the /etc//configfile -> to somewhere in /nix which is read-only for you. so it’s up to you to erase the symlink and put a real file there. One could automate this with a systemd service that runs on startup.
Another way to do this, is hack up the systemd service, assuming the service will accept the location of the config file as a cmd line argument. This is non-standard and can be fiddly in nix.
I don’t know of a better way.
On Guix system it is recommended to manage anything in etc via a “service” which will be written/configuerd in scheme and has deploy and rollback semantics.
For config that lives in $HOME there is guix home and guix home services, which parallel the system for /etc and system services, and even work on other operating systems.
I use https://github.com/nix-community/home-manager to manage $HOME. I use that to manage my git config and bashrc. I also use it to declare which directories should survive a reboot. e.g. I persist ~/.steam and ~/.thunderbird, “Documents/”, a few others. But everything else, e.g. ~/.vim (which I only use in an ad-hoc manner) is wiped.
Even that leaves some blob-like state: I persist “.config/dconf”. Ideally that could be managed declaratively, but I haven’t seen a workable solution.
That works fine for building new machines well, but a typical Linux machine is built far less frequently than its updated. For example, I’ve managed machines with packages/Puppet/Ansible in the past, and occasionally run into situations where the machine state according to packages/Puppet/Ansible no longer matches the actual machine state:
apt-get install $x
followed byapt-get purge $x
leaves live config (e.g. files in /etc/pam.d)The result is that even just covering /etc and /usr, machines are brittle, and occasionally need to be rebuilt to have confidence.
Yes, it does make quick hacks hard/impossible. It is possible to do some quick hacks on the box (
systemctl stop foo
, for example), and nixpkgs is designed so that various parts can be overridden if needed.When we climb the ladder of abstraction, and lose access to easily change the inner workings of lower levels, it looks like (and is!) restrictive. In the same way I wouldn’t modify a binary in a hex editor to perform deployments, nor would I make live changes to a Docker image, I aim to not SSH to a machine to mutate it either. I prefer my interactions with lower-level abstractions to be mediated via tooling that applies checks-and-balances.
I don’t make recommendations without understanding requirements, but NixOS/Guix is at least a novel approach to distributions, which might be interesting to OS folks.
NixOS/Guix might have come too late for industry: containers also aim to manage system complexity, and do a good job of it. I think NixOS/Guix offers good solutions for low-medium scale, and as a way to build container images.
I only use NixOS/Guix for my personal infra, and manage all those machines in a declarative manner (other than out-of-scope things such as databases like ~/.config/dconf and postgres).
Yes, DB schema migrations is an interesting case where a declarative approach would be nice to have: it’s much easier to reason about a single SQL DDL than a sequence of updates.
A similar problem I have is the desire for declarative disk partitions: ideally I could declare my partition scheme, and apply a diff-patch of mutations to make the declaration reality. It would only proceed if it was safe and preserved the underlying files. It’d likely only be possible under particular constraints (lvm/btrfs/zfs ?). Even then that’s hard to get right!
You too!