Hi all,
I’ve been using NixOS for a while now (About a month now) and I’ve been loving it, but I’ve had some thoughts lately.
I understand that Nix(OS)'s claim to fame is the fact that packages are reproducible. All dependencies are versioned and all packages are rollback-able (although not sandboxed). With proper maintenance (nix-collect-garbage
mostly), the problem with space is mostly mitigated.
But what if a package’s dependencies are out of date? These just stay out of date with their possible security problems as well. Not just that but it’s (nearly) impossible to actually do your own manual imperative editing of packages to solve a quick problem since everything is declarative.
Not just this, but Nix uses mostly its own configuration methodology, so isn’t this a maintenance nightmare as config files change and options are added/removed? Home manager is a prime example of this potential problem.
Plus more technologies being introduced on top of it to solve problems that seem already solved? (Flakes mostly come to mind).
I have come to the realiziation that, unlike a traditional distro like Arch/Alpine which I used previously, if maintenance dies I cannot feasibly maintain it myself, since it’s mostly “magic”. The upkeep of all the configurations plus all the dependency packages, and making sure each package compiles and matches the build configuration is a nightmare. I can barely do it with my own personal projects.
Anyways that’s kinda it just expressing thoughts about it. I do love Nix(OS) and plan to continue using it. It’s amazing, and its capabilities are matched by few to none, and from a user perspective it is an extremely seamless and simple OS. It’s mostly from a maintainer perspective that I had.
The out of date problem you mention is something Nix contemplates. As of a couple hours ago, if you try to install Etcher (Balena Etcher, that is), you will get a message saying there’s an out of date dependency: Electron.
You can still try to install End of Life packages, but you have to type an instruction the ‘compiler’ tells you to type out. In other words, you have to be deliberate about installing out of date dependencies.
The other problem I understood it as “if I declaratively do this and then imperatively do that, how do I keep track of it all?”. If that is indeed what you’re asking, you’re right. That’s a problem. That’s why I try to keep everything in the config.
I’ve been using Nix now for a couple of months and the configuration file has been a great friend. Sometimes I don’t know how to configure something and I get lost and worried, but the community has helped me to fix my problems- .
I guess I could’ve worded this better but my second problem was: I would like to do everything declaratively. What do I do when a package doesn’t have its own declarative configuration options? Before it was simple because it was imperative, so I could just change the config file, but not so much in NixOS.
You can still imperatively edit configs for packages where you don’t have / aren’t using the declarative config. You’ll just have the same reproducibility issues that you’d have on other systems. In general all the declarative NixOS modules do is generate the config files you’d normally write yourself, sometimes with some extra error checking. I’ve been doing this for my neovim config because I haven’t cared to port it to the module’s way and I want it to work on systems without nix.
Gotcha yeah that makes sense, so I’ll start doing this as well.
Having a config file means a package can be done declaratively. You can just use a nix option to create the config file.
I didn’t know this before, but a lot of comments said the same! I think I’ll start doing this.
Any package can be “edited” using its
overrideDerivation
function. You can pass new configureFlags, buildInputs, a new src, etc. It’s all additive too, so when something else about the package changes in Nixpkgs, that’ll propagate to your “edited” package too.Config files for some service at runtime and the packages themselves are two separate domains. The former is handled by NixOS. In order to “modify” the runtime configuration, you set options inside a NixOS module such as your configuration.nix. If you wanted to place a config file somewhere in
/etc/
or configure a systemd service, you’d use theenvironment.etc
orsystemd.services
options. They’re a bit like “primitives” as they’re rather low-level in NixOS terms but so is editing a config file in an imperative distro. NixOS modules usually use these “primitives” internally to offer more abstract options.services.paperless.enable
internally sets up a systemd service viasystemd.services
which runs paperless with the declared configuration for example.So I can use something like
systemd.services
to make my own services as well? Because I’ve been wondering how to do this as well.Absolutely. Your NixOS config is also just a NixOS module. You could even have it have options if you’d like to.
I haven’t done this yet because I didn’t need it, but I think you have the option to install newer packages by creating a nixpkgs overlay. If the build process didn’t change between versions, it should be pretty straightforward. See https://nixos.wiki/wiki/Overlays, section “Overriding a version” for an example. Better yet create an issue on the nixpkgs bugtracker, or even better file a pull request for the updated package.
Edit: you could even define a new updated package just for the package that depends on it and then pass that new package as a normal override. No need to update the package systemwide.
Ooh yeah I’ll look into that thank you!
what if a package’s dependencies are out of date?
This is rarely the case as we usually don’t keep older patch versions or whatever. Most packages will just be updated “in-place”. We might keep a few major versions of some major packages though if some other packages have a hard dependency on some older API/ABI. When that happens and an old major version goes EOL/has security issues, it’s marked as insecure and you’d have to explicitly opt into using it by allowing its version in your config.
it’s (nearly) impossible to actually do your own manual imperative editing of packages to solve a quick problem since everything is declarative.
You can do your own declarative “editing” of packages: Overrides allow you to override any dependency of a package and receive a package where that dependency is the other thing you put in.
Overlays allow you to “edit” packages in the context of a package set where the package’s dependants in the set also receive the “edited” package as their dependency.
It’s fairly normal to have an overlay in your config to customise a few packages to your liking. Anything that needs
youtube-dl
getsyt-dlp
with the youtube-dl executable alias in mine for example: https://github.com/Atemu/nixos-config/blob/b79f42793a709db083cf53867f85d5d46e41eb69/overlays.nix#L29-L33. Stuff like that.Also note that, if a package is broken, it’s usually best to fix it upstream rather than patching around upstream in your own config. The package being unbroken for every NixOS user instead of just yourself is one PR away; it’s super easy to contribute to Nixpkgs.
Nix uses mostly its own configuration methodology, so isn’t this a maintenance nightmare as config files change and options are added/removed?
In NixOS, this doesn’t happen very often. Most options have been there for years and go unchanged for years aswell. At least in terms of API; they might do different things internally to achieve the options’ goal but you don’t need to care about that; you just state your intent. There are many ways to install i.e. systemd-boot to your ESP but you only care that it’s installed, not how.
When a breaking change happens in the options’ API, you’ll know about it at eval time. It’ll show you an error stating that e.g. the option has been renamed to so and so and perhaps the semantics changed. Many times it’ll just be an eval warning even, stating that the option has been renamed and has been set to your old option’s value but you should move over because this fall-back will be removed in the next release.
Note that if you don’t like breaking changes coming in willy-nilly, the stable channel (23.05 currently) would be for you: It restricts such option changes and you only have to change your config to accommodate option changes twice a year when a new release comes out. As I said though, breaking changes don’t happen very often for your average NixOS config even on the unstable channel. This isn’t really as much of an issue as you might think.
Can’t really speak for home-manager as my use of it is quite limited and it’s a nix-community project, not a NixOS one (different quality standards).
I have come to the realiziation that, unlike a traditional distro like Arch/Alpine which I used previously, if maintenance dies I cannot feasibly maintain it myself, since it’s mostly “magic”.
That’s just because you don’t have experience packaging or maintaining Nix packages yet. If you didn’t know how to package Arch/Alpine packages, you would be just as screwed if maintenance was dropped.
Once you’ve done a few patches to packages or even packaged something yourself, this “magic” will become more and more disenchanted.
The upkeep of all the configurations plus all the dependency packages, and making sure each package compiles and matches the build configuration is a nightmare.
Not quite sure what you mean here. Could you point out some concrete examples of that?
Sorry for the late reply. In the 2 weeks I’ve still kept using it and I learned a lot! But a lot of my musings still stand, at least in my mind, but after thinking a little longer, a lot of the thoughts I had also apply to other distros as well.
To answer what you asked in final, a good hypothetical that might answer it is something like GNOME. If the nixos channel blew up in a doomsday scenario, I’d be stuck maintaining my packages myself, right? And I use the doomsday scenario, because the problems here apply for self-made packages as well, but it’s easier for me and maybe others to wrap their head around the problem I’m getting at. So with GNOME, I’d have to update every single dependency manually in my nix files. With something like Arch/Alpine I could just have those files, and they have these really neat scripts where I can just bump the version, and it’ll download, set the hash up, and bump the version all for me. With Nix there are no such tools. I can’t just automate the process, nor is it feasible to do this type of thing manually. As new features are added, so are new options needed to activate those features. And yes, although in this scenario, I would probably just opt to not add these options and set it up myself, when making a package for the general public this isn’t the case. If GNOME adds a feature (idk why I picked GNOME I haven’t used it in like 5 years) to have extensions managed by the package manager, I’d have to add an option for what extensions are needed and all that. And this is a lot of work, at least as far as I know. The extensions would also have to be packaged.
a good hypothetical that might answer it is something like GNOME. If the nixos channel blew up in a doomsday scenario, I’d be stuck maintaining my packages myself, right?
I’m not sure what you mean by “doomsday scenario” or a nixos channel “blowing up”.
So with GNOME, I’d have to update every single dependency manually in my nix files. With something like Arch/Alpine I could just have those files
If they require updating, you’d have to update every single dep on Arch/Alpine too.
If you only needed to modify one dep, you’d create an overlay with that package modified and that’d be about as simple as on those other distros, perhaps even easier to manage in the long run.
Not sure what you mean by “have those files”? What files? The package definitions? Why wouldn’t you have those in Nixpkgs?
they have these really neat scripts where I can just bump the version, and it’ll download, set the hash up, and bump the version all for me. With Nix there are no such tools. I can’t just automate the process
https://github.com/ryantm/nixpkgs-update
nor is it feasible to do this type of thing manually
Why?
As new features are added, so are new options needed to activate those features.
Not necessarily. Many times a NixOS modules simply uses an RFC42-style
settings
option which accepts arbitrary, well, settings. I haven’t updated the dnscrypt-proxy module in ages but you can still use all newly added configuration options.Also, it just… doesn’t happen all that often. It’s not something you, as a user, usually need to concern yourself with. Someone else will likely bump the packages; the distro won’t just die off over night.
If GNOME adds a feature (idk why I picked GNOME I haven’t used it in like 5 years) to have extensions managed by the package manager, I’d have to add an option for what extensions are needed and all that. And this is a lot of work, at least as far as I know. The extensions would also have to be packaged.
Someone has already done that work. Even if they hadn’t, you could still just imperatively install the extensions. I do that on my tablet where I use GNOME.
I also don’t manage my firefox plugins using Nix. I could, someone built support for that into home-manager but I can choose not to.
Most derivations are pretty flexible; the ones that aren’t, however, will require you to write your own overlay to fix them. Or just for kthem entirely. This is one of the advantages in Nix in that you can create reproducibility at any granularity. Writing and using your own derivation is complex though. Most packages provide more than enough knobs to change their configuration on their own in my experience though — my current Nix build uses no derivations I had to write myself.
Home Manager and Nix itself are versioned so I don’t understand your complaint about config changing. If you’re happy with how your system works just don’t update it to a newer version. If you do, as in any other software, you risk breakage. The advantage of Nix in this scenario obviously is that rolling back in the case of an upgrade going wrong is incredibly trivial.
I could’ve worded the configuration part a bit better. My gripe wasn’t necessarily with that, but more with “If I ever had to make my own package from scratch including dependencies, this would be practically impossible” Nix’s derivations and other packaging information is crazy complex and keeping track of versioning, etc. is a nightmare. I think often about doomsday scenarios for systems. It happens, just look at CentOS and all that, so my main thing was if something like that happened, could I maintain the packages I use manually, and the answer was no. Of course I’m not in a doomsday situation, so I’m fine with it as it is. It’s just a thought I had, and that was my conclusion.
It’s not as hard as you think, since you can just copy some other package for a skeleton and substitute your own files. There are just a few files to do a basic package
Derivations are kinda complicated but you can definitely get them if you try! There’s nothing super magical about them. As opposed to the rest of Nix which can feel extremely and unfortunately magical…
Gotcha I’ll start playing around with derivations. I also just came to the realization that because of the magic of Nix, I can try these things, and if it breaks it, I can just roll back.
NixOS packaging is really not complex. The ease and speed of creating a Nix package is a large part of the reason for why there are so many packages. I regularly make packages myself and for the most part it is very simple.
The way NixOS is, the initial setup of all the different things you would want is incredibly time consuming and it has a very very steep learning curve. It was incredibly difficult for me to set everything up. I tried to make it work and then ran away 4 times now, each time starting from the configuration I’ve had so far, and building up on it. I still haven’t been able to perfect my configuration, and I’ve been on NixOS (this time) since mid-June. I haven’t been working on it actively, but I have done some work on it. NixOS is just too complex and too much for me to wrap my head around. Personally, I’m leaving it for something else, I’m thinking of Void, and I might go back to Arch for a while, I don’t know. Fedora seemed promising, but after the recent telemetry stuff, I crossed it off my list. Tumbleweed seems alright? I’ll see. But I totally get it.
I too think that NixOS is amazing. It is really unique (Guix is similar but not quite) yet it is very difficult to learn and maintain properly.
The main problem with NixOS right now is, in my opinion, the scattered documentation. You often can’t understand a topic without cross-referencing the manual, nixos wiki, nixos search (and nixpkgs and some scattered personal blogs if you’re really unlucky). But if you stick around and adapt to this it’s very easy to do stuff that takes a lot of effort on other distros with a few lines in your config.
While we’re on the topic: What’s a great resource to learn about flakes? I can’t seem to find a great answer that also shows why they are better and when.
They’re still unstable and fully optional. When you’re at the point where you could benefit from flakes, you’ll know it. Ignore them for now.
The most tangible difference to a NixOS user would be that they replace channels. If you’re contempt with channels, no need to rush to flakes.Hey, sorry for the late reply. I found the blog by xiaoso quite good, and this one also isn’t too bad. But I never found one true source which explained it satisfactorily to me. It’s probably best if you just browse through other people’s configuration and piece it all together from that. From what I understood, flakes have 3 main uses:
- They replace nix channels. If you want to switch between stable and unstable it’s pretty easy to do through flakes. Also, if you need any modules (like home manager or agenix, for encrypting secrets) you can simply import it as an import for your flake.
- You can “modularize” your configuration. You can describe multiple systems in a single flake so you can have your desktop and laptop be built from the same flake, but with different packages installed. This is the part that I use most and honestly find most useful.
- You can quickly have a development environemnt through flakes. You could use a flake per project, have all your dependencies as inputs in your dev flakes and never clutter your system with various dev tools
Nixos is riddled with stuff that you just “have to know” which can be quite frustrating. The lon ger you stick with it, the easier it gets though.
Thank you, that’ll definitely help! Looks like I have some more stuff to dig into :)
I’m personally very happy with tumbleweed. It’s been very stable, and has the built in rollback feature on the off chance an update played bad with your system (I’ve only needed to use it two or three times over the last few years across three different computers). Tumbleweed also integrates super well with plasma.
Ooh if you’re thinking of trying something new I recommend Alpine. An extremely underrated distro for a DIYer. It’s really lightweight and simple and its packaging system is a breeze to write packages for (for things you’d usually use the AUR for, since there isn’t an equivalant for Alpine AFAIK). Void is also fun I ran that for a year. Keep in mind, I’m only talking fun. For a good distro that will Just Work™, Alpine is fine, but I think Arch wins on that front.
NixOS is a journey and I have the privelage of having two systems, one “Home” system running Arch that I use usually and my “Roaming” system which I run whatever and is what I take to class and stuff because usually I only use it to take notes meaning minimum requirement is “Be able to log into a tty so I can write a text file”. So being able to use that for NixOS has helped a lot, since if something goes wrong, I can just ssh into my “Home” machine to get work done.
I do overlays of software to patch it all the time. Eventually I’ll package it, but it needs upstream fixes, so I’ll try to package my own fork