Ask HN: Does NixOS live up to its promise?

6 points by tiffanyh ↗ HN
NixOS.org summaries itself as “Reproducible, Declarative, Reliable”.

But you cannot specify the exact package version # in you build config file to use (lack of being declarative).

As such, packages get updated making your build environment change over time, which seems to be inconsistent with the principle of being reproducible and reliabile (since version changes might break your environment).

The principles of Nixos sounds wonderful and would solve real world problems. But does NixOS deliver on that without being able to specify exactly package version #s?

Note: see this Github ticket from 6+ years ago (2015).

https://github.com/NixOS/nixpkgs/issues/9682

4 comments

[ 0.25 ms ] story [ 13.6 ms ] thread
Supporting all older versions of packages would be a nightmare to maintain - not only from a security perspective.

You have three options afaik:

1. Pin your package repository

2. As answered in your last linked issue: specify a package with git

3. Build it yourself

I think this compromise is gold. Update your package registry and get the latest stuff (or even bleeding edge if you point to unstable), pin manually when you care about the version.

Let me give a real world example, setting up a web/database server.

Are you saying that I could do the follow (pseudo-code) in my configuration.nix file just by pinning?

-------

nixOS = 21.11 # use this as the base

add_packages = [ "postgres" = 14.1, "redis" = 6.2.6, "nginx" = 1.21.6 ]

-------

Also, where does Flakes fit into this picture?

Basically, albeit a bit more verbose. If you're looking to do this on a per-project basis, then yeah Flakes would be a good choice.

See https://nixos.wiki/wiki/Flakes#Input_schema for some idea on how it would look.

The main obstacle for you here is learning the Nix language and how to use it for nix packages. It's not an easy task, but it does meet your requirements.

https://nix.dev/ is a good resource in addition to https://nixos.org/manual/nixos/stable/ and https://nixos.org/guides/nix-pills/

Preface: Nix is sometimes difficult because it forces you to be explicit about what you mean. For instance, your example specifies particular versions of end-user packages. Do you want all of them to use the same shared libraries? Do you want each of them to use the libraries that they were tested with at the time those specific versions were released? Should we use the latest secure+patched libraries, but the older application versions? Do you want the patches to your applications known at time of release, or the latest? Most systems don't allow this much specificity or power.

Yes. An example that i had to do recently. I forget the exact issue, but I wanted to express the thought: "keep the rest of my system up to date, but pin only the notmuch package to an older version. Oh, and to make sure it is not unspecified: that older version should also use the dynamic libraries that it is tested to work with, potentially older than the rest of my system."

in code; ``` nixpkgs.overlays = [(self: super: { notmuch = nixpkgs-old.legacyPackages.x86_64-linux.notmuch; })]; ``` Where nixpkgs is basically 21.11 and nixpkgs-old is a particular git commit hash.

But you can express other nuanced thoughts as well: - bring in an old application, but don't change anything else on my system (non-interference) - patch some core library, AND recompile EVERYTHING that uses it (global replacement) - only replace a core library for the software used for a particular service, no where else (targeted patching) - change some ./configure flags but otherwise track the latest security updates for a release, recompile only the things needed (dynamic customization) - recompile everything with optimization flags (source based distro) - only update what github revision used as source for an application, otherwise everything the same (stay on bleeding edge for a specific application)

I think people tend to overthink Flakes, they are a standard code organization schema and an entrypoint into the Nix language that ensures everything is tracked and locked. It makes things reproducible, both the successes and (perhaps more important!) the bugs and failures.