diff options
Diffstat (limited to 'src/blog/linking.kuht')
| -rw-r--r-- | src/blog/linking.kuht | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/blog/linking.kuht b/src/blog/linking.kuht new file mode 100644 index 0000000..f994765 --- /dev/null +++ b/src/blog/linking.kuht @@ -0,0 +1,245 @@ +<import "base.kuht" as "base" /> + +<head> + <title>What Other Distros Can Learn from NixOS</title> + <meta name="description" content="Traditional distros will either have delayed updates or unstable updates. NixOS allows us to have both." /> +</head> + +<body> +<article> +<h1>What Other Distros Can Learn from NixOS</h1> + +<p> + As a warning, this blog post contains the ramblings of an Arch user who + barely knows what a flatpak is and has like, three of them on their system. + Their background is in web deployment pipelines and they're trying to apply + their personal beliefs to Linux distributions, like an idiot, without even + making a proof-of-concept. Reader discretion is advised. +</p> + +<p> + One debate that often comes up is static versus dynamic linking. Most Linux + distributions try to manage dependencies by dynamically linking them. This can + be good, because if a previous version of a library contains a bug, then it's + easy to distribute the bug fix and have it apply to all applications + simultaneously. The downside is that if a newer version of a library contains + a bug, or a backwards-incompatible change, then that will apply to all + installed applications. Dynamic linking is a double-edged sword that makes it + both easier to fix bugs and easier to create new ones. +</p> + +<p> + But NixOS offers strict control over both the release and use of libraries, + which allows applications to get both the ease of rollout that comes with + dynamic linking, and the control that comes from static linking. +</p> + +<h2>Background</h2> + +<p> + When an application is installed on NixOS, it is not put in the + <code>/bin</code> folder. In fact, this folder is almost entirely empty. + Instead, it goes to <code>/nix/store</code>, in a directory with an + unreadable hash. Then, when you boot the system, the files for your system + applications are symlinked into <code>/run/current-system/sw</code>, which is + in the <code>PATH</code>, so these applications can run in your terminal. +</p> + +<p> + But that's only system applications. For libraries, the application sets its + own <code>LD_LIBRARY_PATH</code> variable. This tells the dynamic linker + where to fetch the required libraries from. This isn't exactly what the file + looks like, but you can imagine it looking something like this: +</p> + +<pre> +#!/path/to/bash +LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/nix/store/naioghuraopjfi4738-libgit2-2.23" +export LD_LIBRARY_PATH +exec -a git "$@" +</pre> + +<p> + The benefit of this system is that you can multiple versions of the same + library installed on your system, and different applications can depend on + different versions, depending on what they need. +</p> + +<p> + I want to note that there's nothing special about NixOS that would make this + impossible on other systems. Flatpak already allows applications to bundle + their own versions of libraries, and Snap has a similar system. So I think + other distros can still benefit from this system. +</p> + +<h2>Testing</h2> + +<p> + Before I go into the benefits of the system described above, I'll touch on + something that distros can do already, but that specifying dependency + versions might make easier. +</p> + +<p> + Before you can even update the repository, you'll have to test the library. + Hopefully, the maintainer of the library has already done this for you, by + creating a suite of unit tests that they ran before creating the release. I + suppose it wouldn't hurt to double check. +</p> + +<p> + The more interesting test you'll need to run is similar to what + <a href="https://github.com/rust-lang/crater">crater</a> does for the Rust + ecosystem. Whenever a change is made to the language, Rust runs crater to + determine if the change would cause a breaking change for any packages on + crates.io. It's a very brute-force way to test for new bugs. +</p> + +<p> + In order for this to work, not only does the library need a unit test suite, + but so does every application that depends on that library. You'll build + every single dependent against the newer version of the library, and then + test all of them to see if anything breaks. +</p> + +<p> + Inevitably, some applications will fail under a new version of a library. + This doesn't necessarily need to be because of a problem in the library + itself, but it could be due to a transient failure in the application. In + such a scenario, the application's dependency would be updated to say + <code>3.13</code> instead of <code>3</code>, so it doesn't block other + applications from using the newer version. +</p> + +<p> + It would also be beneficial to store somewhere in the package which version + of each dependency an application was last tested with. Then, if you want to + be extra safe, you can delay upgrading the dependency until you know that a + test has been run on the latest dependencies. +</p> + +<h2>Beta Channel</h2> + +<p> + The delayed release of packages is what separates Arch Linux from Manajaro. + Some users are more interested in being on the bleeding edge than others. I + don't see any reason why two separate package repositories are needed for + this. We can allow users to opt-in to the bleeding edge for specific packages + faster. These people can submit bug reports before the new features make + their way to regular users. +</p> + +<p> + NixOS has this in the form of the <code>unstable</code> channel. Users can + opt-in to using the unstable channel to get an experience more similar to a + rolling release distro. And judging from some Reddit threads, there are + people using the unstable channel regularly. This makes sense to me, since + not everyone who uses Nix is there for stability. Some people just like + having a central config file. NixOS also lets people go one step further and + use <code>unstable</code> for specific packages, but leave the rest of their + entire system stable. +</p> + +<p> + Other distros do have this. Most commonly this comes in the form of an LTS + variant of the distro, which most users are expected to stay on. The non-LTS + variant is often treated as a beta. +</p> + +<h2>Rollout</h2> + +<p> + The rest of the ideas presented in this post are ideas that can be done as + long as you have a way to pin dependency versions, but they're not done by + NixOS. How important these are is debatable, since NixOS already tests their + stable channels before releasing them. +</p> + +<p> + Not every package is of equal importance. A change to a library affecting + pacman is far more critical to a library that only affects GIMP. But thanks + to the system we have here, it doesn't need to affect every package at the + same time. We can rollout a library change to less important packages first + before we apply it to every library. +</p> + +<p> + To give an example of how this would work, let's say a new library version + releases, and it affects both pacman and GIMP. For this to work, we'd need to + assign a priority level to every package. Pacman would probably be a level 2 + package, meaning it's very important. There should only be a few level 1 + packages. GIMP would be level 4, so not very important. As a level 4 package, + GIMP would be one of the first packages to use the new version of the + library. After a couple days, pacman would also start using the new library. +</p> + +<h2>Rollback</h2> + +<p> + So with all that in mind, what happens when a library actually is bad? Well, + marking the library version as bad is luckily pretty simple. We just update + the version resolver to say that if a package asks for version + <code>3</code>, don't use <code>3.14</code>. Prefer <code>3.13</code> + instead. Pacman already caches older versions of packages, so you might not + even need to re-install <code>3.13</code>. +</p> + +<p> + Of course, rolling backwards isn't always safe. Some newer packaages might + already be using features of <code>3.14</code> that don't exist in + <code>3.13</code>. To partially resolve this, we can run the test suite + against each package before downgrading to <code>3.13</code>. Hopefully + everything will pass, but if a particular package does not, then we can set + that package specifically to require a minimum of <code>3.14</code>. We can + also mark this downstream package as bad, and prevent new installations of it + until a patch is made. +</p> + +<h2>Distribution</h2> + +<p> + There's one thing here that we can't control: the distribution. Meaning, we + don't know when the user is going to run an upgrade. Unlike in Windows land + or web land, we don't run the upgrade automatically. Some systems will at + least automatically check for updates and notify the user when there is one, + but there's usually no distinction between critical bug fixes and feature + updates. +</p> + +<p> + I would recommend having a daemon that at least automatically downgrades in + the case of bad library versions. Since we can cache older versions of the + library, this wouldn't require too much network activity. And we can always + give the user an option to disable it. +</p> + +<p> + NixOS actually does support full automatic upgrades in the background. Some + NixOS users report that because NixOS is so stable, they feel comfortable to + just letting everything update in the background without intervention. The + NixOS wiki provides this example on how to do so. +</p> + +<pre> +system.autoUpgrade = { + enable = true; + flags = [ + "--print-build-logs" + ]; + dates = "02:00"; + randomizedDelaySec = "45min"; + allowReboot = false; # Set to true if you want automatic reboots +}; +</pre> + +<h2>Conclusion</h2> + +<p> + I don't want to say none of these solutions come with caveats. NixOS has + trouble running arbitrary executables because of how it goes about + accomplishing its goals. The way things are set up on NixOS can sometimes be + confusing to newcomers, and I understand why a Linux distro wouldn't want to + copy everything from NixOS. But I think even a best-effort attempt at some of + the ideas that NixOS provides could provide major benefits for stability. + It's just about choosing the right compromises. +</p> |
