Thicket data repository for the EEG
1{
2 "id": "https://ryan.freumh.org/nix.html",
3 "title": "Nix",
4 "link": "https://ryan.freumh.org/nix.html",
5 "updated": "2025-02-03T00:00:00",
6 "published": "2022-12-14T00:00:00",
7 "summary": "<div>\n \n <span>Published 14 Dec 2022.</span>\n \n \n <span>Last update 3 Feb 2025.</span>\n \n </div>\n \n <div> Tags: <a href=\"/technology.html\" title=\"All pages tagged 'technology'.\">technology</a>. </div>\n \n \n\n <p><span>I originally wrote this as an explainer for <a href=\"hillingar.html\">Hillingar</a> before separating it into its own\npage.</span></p>\n\n\n\n\n<img src=\"./images/nix-snowflake.svg\">\n\nNix snowflake<a href=\"#fn1\">1</a>\n\n<p><span>Nix is a deployment system that uses cryptographic\nhashes to compute unique paths for components<a href=\"#fn2\">2</a>\nthat are stored in a read-only directory: the Nix store, at <code>/nix/store/<hash>-<name></code>. This\nprovides several benefits, including concurrent installation of multiple\nversions of a package, atomic upgrades, and multiple user environments\n<span><a href=\"#ref-dolstraNixSafePolicyFree2004\">[1]</a></span>.</span></p>\n<p><span>Nix uses a declarative domain-specific language\n(DSL), also called Nix, to build and configure software. The snippet\nused to deploy the DNS server is in fact a Nix expression. This example\ndoesn’t demonstrate it, but Nix is Turing complete. Nix does not,\nhowever, have a type system.</span></p>\n<p><span>We use the DSL to write derivations for software,\nwhich describe how to build said software with input components and a\nbuild script. This Nix expression is then ‘instantiated’ to create\n‘store derivations’ (<code>.drv</code> files), which is\nthe low-level representation of how to build a single component. This\nstore derivation is ‘realised’ into a built artefact, hereafter referred\nto as ‘building’.</span></p>\n<p><span>Possibly the simplest Nix derivation uses <code>bash</code> to create a single file containing <code>Hello, World!</code>:</span></p>\n<div><pre><code><span><a href=\"#cb1-1\"></a><span>{</span> <span>pkgs</span> <span>?</span> <span>import</span> <nixpkgs> <span>{</span> <span>}</span> <span>}</span>:</span>\n<span><a href=\"#cb1-2\"></a></span>\n<span><a href=\"#cb1-3\"></a><span>builtins</span>.<span>derivation</span> <span>{</span></span>\n<span><a href=\"#cb1-4\"></a> <span>name</span> <span>=</span> <span>"hello"</span><span>;</span></span>\n<span><a href=\"#cb1-5\"></a> <span>system</span> <span>=</span> <span>builtins</span>.currentSystem<span>;</span></span>\n<span><a href=\"#cb1-6\"></a> <span>builder</span> <span>=</span> <span>"</span><span>${</span>nixpkgs.bash<span>}</span><span>/bin/bash"</span><span>;</span></span>\n<span><a href=\"#cb1-7\"></a> <span>args</span> <span>=</span> <span>[</span> <span>"-c"</span> <span>''echo "Hello, World!" > $out''</span> <span>];</span></span>\n<span><a href=\"#cb1-8\"></a><span>}</span></span></code></pre></div>\n<p><span>Note that <code>derivation</code>\nis a function that we’re calling with one argument, which is a set of\nattributes.</span></p>\n<p><span>We can instantiate this Nix derivation to create a\nstore derivation:</span></p>\n<pre><code>$ nix-instantiate default.nix\n/nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv\n$ nix show-derivation /nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv\n{\n "/nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv": {\n "outputs": {\n "out": {\n "path": "/nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello"\n }\n },\n "inputSrcs": [],\n "inputDrvs": {\n "/nix/store/mnyhjzyk43raa3f44pn77aif738prd2m-bash-5.1-p16.drv": [\n "out"\n ]\n },\n "system": "x86_64-linux",\n "builder": "/nix/store/2r9n7fz1rxq088j6mi5s7izxdria6d5f-bash-5.1-p16/bin/bash",\n "args": [ "-c", "echo \\"Hello, World!\\" > $out" ],\n "env": {\n "builder": "/nix/store/2r9n7fz1rxq088j6mi5s7izxdria6d5f-bash-5.1-p16/bin/bash",\n "name": "hello",\n "out": "/nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello",\n "system": "x86_64-linux"\n }\n }\n}\n</code></pre>\n<p><span>And build the store derivation:</span></p>\n<div><pre><code><span><a href=\"#cb3-1\"></a><span>$</span> nix-store <span>--realise</span> /nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv</span>\n<span><a href=\"#cb3-2\"></a><span>/nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello</span></span>\n<span><a href=\"#cb3-3\"></a><span>$</span> cat /nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello</span>\n<span><a href=\"#cb3-4\"></a><span>Hello,</span> World!</span></code></pre></div>\n<p><span>Most Nix tooling does these two steps\ntogether:</span></p>\n<pre><code>$ nix-build default.nix\nthis derivation will be built:\n /nix/store/q5hg3vqby8a9c8pchhjal3la9n7g1m0z-hello.drv\nbuilding '/nix/store/q5hg3vqby8a9c8pchhjal3la9n7g1m0z-hello.drv'...\n/nix/store/zyrki2hd49am36jwcyjh3xvxvn5j5wml-hello\n</code></pre>\n<p><span>Nix realisations (hereafter referred to as\n‘builds’) are done in isolation to ensure reproducibility. Projects\noften rely on interacting with package managers to make sure all\ndependencies are available and may implicitly rely on system\nconfiguration at build time. To prevent this, every Nix derivation is\nbuilt in isolation (without network access or access to the global file\nsystem) with only other Nix derivations as inputs.</span></p>\n<blockquote>\n<p><span>The name Nix is derived from the Dutch word\n<em>niks</em>, meaning nothing; build actions do not see anything that\nhas not been explicitly declared as an input <span><a href=\"#ref-dolstraNixSafePolicyFree2004\">[1]</a></span>.</span></p>\n</blockquote>\n<h2>Nixpkgs</h2>\n<p><span>You may have noticed a reference to <code>nixpkgs</code> in the above derivation. As every input\nto a Nix derivation also has to be a Nix derivation, one can imagine the\ntedium involved in creating a Nix derivation for every dependency of\nyour project. However, Nixpkgs<a href=\"#fn3\">3</a> is a large repository of\nsoftware packaged in Nix, where a package is a Nix derivation. We can\nuse packages from Nixpkgs as inputs to a Nix derivation, as we’ve done\nwith <code>bash</code>.</span></p>\n<p><span>There is also a command line package\nmanager installing packages from Nixpkgs, which is why people often\nrefer to Nix as a package manager. While Nix, and therefore Nix package\nmanagement, is primarily source-based (since derivations describe how to\nbuild software from source), binary deployment is an optimisation of\nthis. Since packages are built in isolation and entirely determined by\ntheir inputs, binaries can be transparently deployed by downloading them\nfrom a remote server instead of building the derivation\nlocally.</span></p>\n\n\n<img src=\"./images/nixpkgs.png\">\n\nVisualisation of Nixpkgs<a href=\"#fn4\">4</a>\n\n<h2>NixOS</h2>\n<p><span>NixOS<a href=\"#fn5\">5</a> is a Linux distribution\nbuilt with Nix from a modular, purely functional specification <span><a href=\"#ref-dolstraNixOSPurelyFunctional2008\">[2]</a></span>. It has no traditional filesystem\nhierarchy (FSH), like <code>/bin</code>, <code>/lib</code>, <code>/usr</code>, but\ninstead stores all components in <code>/nix/store</code>. The system configuration is managed\nby Nix and configured with Nix expressions. NixOS modules are Nix files\ncontaining chunks of system configuration that can be composed to build\na full NixOS system<a href=\"#fn6\">6</a>. While many NixOS modules are\nprovided in the Nixpkgs repository, they can also be written by an\nindividual user. For example, the expression used to deploy a DNS server\nis a NixOS module. Together these modules form the configuration which\nbuilds the Linux system as a Nix derivation.</span></p>\n<p><span>NixOS minimises global mutable state that –\nwithout knowing it – you might rely on being set up in a certain way.\nFor example, you might follow instructions to run a series of shell\ncommands and edit some files to get a piece of software working. You may\nsubsequently be unable to reproduce the result because you’ve forgotten\nsome intricacy or are now using a different version of the software. Nix\nforces you to encode this in a reproducible way, which is extremely\nuseful for replicating software configurations and deployments, aiming\nto solve the ‘It works on my machine’ problem. Docker is often used to\nfix this configuration problem, but Nix aims to be more reproducible.\nThis can be frustrating at times because it can make it harder to get a\nproject off the ground, but I’ve found the benefits outweigh the\ndownsides, personally.</span></p>\n<p><span>My own NixOS configuration is publicly\navailable<a href=\"#fn7\">7</a>. This makes it simple to reproduce\nmy system (a collection of various hacks, scripts, and workarounds) on\nanother machine. I use it to manage servers, workstations, and more.\nCompared to my previous approach of maintaining a Git repository of\n<code>dotfiles</code>, this is much more modular,\nreproducible, and flexible. And if you want to deploy some new piece of\nsoftware or service, it can be as easy as changing a single line in your\nsystem configuration.</span></p>\n<p><span>Despite these advantages, the reason I\nswitched to NixOS from Arch Linux was simpler: NixOS allows rollbacks\nand atomic upgrades. As Arch packages bleeding-edge software with\nrolling updates, it would frequently happen that some new version of\nsomething I was using would break. Arch has one global coherent package\nset, so to avoid complications with solving dependency versions Arch\ndoesn’t support partial upgrades. Given this, the options were to wait\nfor the bug to be fixed or manually rollback all the updated packages by\ninspecting the <code>pacman</code> log (the Arch\npackage manager) and reinstalling the old versions from the local cache.\nWhile there may be tools on top of <code>pacman</code>\nto improve this, the straw that broke the camel’s back was when my\nmachine crashed while updating the Linux kernel, and I had to reinstall\nit from a live USB.</span></p>\n<p><span>While Nixpkgs also has one global coherent\npackage set, one can use multiple instances of Nixpkgs (i.e., channels)\nat once to support partial upgrades, as the Nix store allows multiple\nversions of a dependency to be stored. This also supports atomic\nupgrades, as all the software’s old versions can be kept until garbage\ncollection. The pointers to the new packages are only updated when the\ninstallation succeeds, so the crash during the Linux kernel upgrade\nwould not have broken my OS install on NixOS. And every new system\nconfiguration creates a GRUB entry, so you can boot previous systems\neven from your UEFI/BIOS.</span></p>\n<p><span>To summarise the parts of the Nix ecosystem\nthat we’ve discussed:</span></p>\n<p><img src=\"./images/nix-stack.svg\"></p>\n<h2>Flakes</h2>\n<p><span>Without going into too much depth, Flakes\nenable hermetic evaluation of Nix expressions and provide a standard way\nto compose Nix projects. With flakes, instead of using a Nixpkgs\nrepository version from a ‘channel’<a href=\"#fn8\">8</a>, we pin Nixpkgs as an\ninput to every Nix flake, be it a project build with Nix or a NixOS\nsystem. Integrated with flakes, there is also a new <code>nix</code> command aimed at improving the UI of Nix.\nYou can read more detail about flakes in a series of blog posts by Eelco\non the topic<a href=\"#fn9\">9</a>.</span></p>\n<h2>References</h2>\n<p><span><span></span></span></p>\n<div>\n<div>\n<span><div>[1] </div><div>E. Dolstra, M. de Jonge, and E. Visser,\n<span>“Nix: <span>A Safe</span> and <span>Policy-Free System</span> for\n<span>Software Deployment</span>,”</span> p. 14, 2004. </div></span>\n</div>\n<div>\n<span><div>[2] </div><div>E. Dolstra and A. Löh,\n<span>“<span>NixOS</span>: A purely functional <span>Linux</span>\ndistribution,”</span> <em>SIGPLAN Not.</em>, vol. 43, no. 9, pp.\n367–378, Sep. 2008, doi: <a href=\"https://doi.org/10.1145/1411203.1411255\">10.1145/1411203.1411255</a>.\n[Online]. Available: <a href=\"https://doi.org/10.1145/1411203.1411255\">https://doi.org/10.1145/1411203.1411255</a>.\n[Accessed: Oct. 13, 2022]</div></span>\n</div>\n</div>\n\n\n\n\n<ol>\n<li><p><span>As ‘nix’ means snow in Latin. Credits\nto Tim Cuthbertson.</span><a href=\"#fnref1\">↩︎</a></p></li>\n<li><p><span>NB: we will use component, dependency,\nand package somewhat interchangeably in this blog post, as they all\nfundamentally mean the same thing – a piece of software.</span><a href=\"#fnref2\">↩︎</a></p></li>\n<li><p><span><a href=\"https://github.com/nixos/nixpkgs\">github.com/nixos/nixpkgs</a></span><a href=\"#fnref3\">↩︎</a></p></li>\n<li><p><span><a href=\"https://www.tweag.io/blog/2022-09-13-nixpkgs-graph/\">www.tweag.io<em>blog/2022-09-13-nixpkgs-graph</em></a></span><a href=\"#fnref4\">↩︎</a></p></li>\n<li><p><span><a href=\"https://nixos.org\">nixos.org</a></span><a href=\"#fnref5\">↩︎</a></p></li>\n<li><p><span><a href=\"https://nixos.org/manual/nixos/stable/index.html#sec-writing-modules\">NixOS\nmanual Chapter 66. Writing NixOS Modules</a>.</span><a href=\"#fnref6\">↩︎</a></p></li>\n<li><p><span><a href=\"https://github.com/RyanGibb/nixos\">github.com/RyanGibb/nixos</a></span><a href=\"#fnref7\">↩︎</a></p></li>\n<li><p><span><a href=\"https://nixos.org/manual/nix/stable/package-management/channels.html\">nixos.org/manual/nix/stable/package-management/channels.html</a></span><a href=\"#fnref8\">↩︎</a></p></li>\n<li><p><span><a href=\"https://www.tweag.io/blog/2020-05-25-flakes/\">tweag.io/blog/2020-05-25-flakes</a></span><a href=\"#fnref9\">↩︎</a></p></li>\n</ol>",
8 "content": "<div>\n \n <span>Published 14 Dec 2022.</span>\n \n \n <span>Last update 3 Feb 2025.</span>\n \n </div>\n \n <div> Tags: <a href=\"/technology.html\" title=\"All pages tagged 'technology'.\">technology</a>. </div>\n \n \n\n <p><span>I originally wrote this as an explainer for <a href=\"hillingar.html\">Hillingar</a> before separating it into its own\npage.</span></p>\n\n\n\n\n<img src=\"./images/nix-snowflake.svg\">\n\nNix snowflake<a href=\"#fn1\">1</a>\n\n<p><span>Nix is a deployment system that uses cryptographic\nhashes to compute unique paths for components<a href=\"#fn2\">2</a>\nthat are stored in a read-only directory: the Nix store, at <code>/nix/store/<hash>-<name></code>. This\nprovides several benefits, including concurrent installation of multiple\nversions of a package, atomic upgrades, and multiple user environments\n<span><a href=\"#ref-dolstraNixSafePolicyFree2004\">[1]</a></span>.</span></p>\n<p><span>Nix uses a declarative domain-specific language\n(DSL), also called Nix, to build and configure software. The snippet\nused to deploy the DNS server is in fact a Nix expression. This example\ndoesn’t demonstrate it, but Nix is Turing complete. Nix does not,\nhowever, have a type system.</span></p>\n<p><span>We use the DSL to write derivations for software,\nwhich describe how to build said software with input components and a\nbuild script. This Nix expression is then ‘instantiated’ to create\n‘store derivations’ (<code>.drv</code> files), which is\nthe low-level representation of how to build a single component. This\nstore derivation is ‘realised’ into a built artefact, hereafter referred\nto as ‘building’.</span></p>\n<p><span>Possibly the simplest Nix derivation uses <code>bash</code> to create a single file containing <code>Hello, World!</code>:</span></p>\n<div><pre><code><span><a href=\"#cb1-1\"></a><span>{</span> <span>pkgs</span> <span>?</span> <span>import</span> <nixpkgs> <span>{</span> <span>}</span> <span>}</span>:</span>\n<span><a href=\"#cb1-2\"></a></span>\n<span><a href=\"#cb1-3\"></a><span>builtins</span>.<span>derivation</span> <span>{</span></span>\n<span><a href=\"#cb1-4\"></a> <span>name</span> <span>=</span> <span>"hello"</span><span>;</span></span>\n<span><a href=\"#cb1-5\"></a> <span>system</span> <span>=</span> <span>builtins</span>.currentSystem<span>;</span></span>\n<span><a href=\"#cb1-6\"></a> <span>builder</span> <span>=</span> <span>"</span><span>${</span>nixpkgs.bash<span>}</span><span>/bin/bash"</span><span>;</span></span>\n<span><a href=\"#cb1-7\"></a> <span>args</span> <span>=</span> <span>[</span> <span>"-c"</span> <span>''echo "Hello, World!" > $out''</span> <span>];</span></span>\n<span><a href=\"#cb1-8\"></a><span>}</span></span></code></pre></div>\n<p><span>Note that <code>derivation</code>\nis a function that we’re calling with one argument, which is a set of\nattributes.</span></p>\n<p><span>We can instantiate this Nix derivation to create a\nstore derivation:</span></p>\n<pre><code>$ nix-instantiate default.nix\n/nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv\n$ nix show-derivation /nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv\n{\n "/nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv": {\n "outputs": {\n "out": {\n "path": "/nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello"\n }\n },\n "inputSrcs": [],\n "inputDrvs": {\n "/nix/store/mnyhjzyk43raa3f44pn77aif738prd2m-bash-5.1-p16.drv": [\n "out"\n ]\n },\n "system": "x86_64-linux",\n "builder": "/nix/store/2r9n7fz1rxq088j6mi5s7izxdria6d5f-bash-5.1-p16/bin/bash",\n "args": [ "-c", "echo \\"Hello, World!\\" > $out" ],\n "env": {\n "builder": "/nix/store/2r9n7fz1rxq088j6mi5s7izxdria6d5f-bash-5.1-p16/bin/bash",\n "name": "hello",\n "out": "/nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello",\n "system": "x86_64-linux"\n }\n }\n}\n</code></pre>\n<p><span>And build the store derivation:</span></p>\n<div><pre><code><span><a href=\"#cb3-1\"></a><span>$</span> nix-store <span>--realise</span> /nix/store/5d4il3h1q4cw08l6fnk4j04a19dsv71k-hello.drv</span>\n<span><a href=\"#cb3-2\"></a><span>/nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello</span></span>\n<span><a href=\"#cb3-3\"></a><span>$</span> cat /nix/store/4v1dx6qaamakjy5jzii6lcmfiks57mhl-hello</span>\n<span><a href=\"#cb3-4\"></a><span>Hello,</span> World!</span></code></pre></div>\n<p><span>Most Nix tooling does these two steps\ntogether:</span></p>\n<pre><code>$ nix-build default.nix\nthis derivation will be built:\n /nix/store/q5hg3vqby8a9c8pchhjal3la9n7g1m0z-hello.drv\nbuilding '/nix/store/q5hg3vqby8a9c8pchhjal3la9n7g1m0z-hello.drv'...\n/nix/store/zyrki2hd49am36jwcyjh3xvxvn5j5wml-hello\n</code></pre>\n<p><span>Nix realisations (hereafter referred to as\n‘builds’) are done in isolation to ensure reproducibility. Projects\noften rely on interacting with package managers to make sure all\ndependencies are available and may implicitly rely on system\nconfiguration at build time. To prevent this, every Nix derivation is\nbuilt in isolation (without network access or access to the global file\nsystem) with only other Nix derivations as inputs.</span></p>\n<blockquote>\n<p><span>The name Nix is derived from the Dutch word\n<em>niks</em>, meaning nothing; build actions do not see anything that\nhas not been explicitly declared as an input <span><a href=\"#ref-dolstraNixSafePolicyFree2004\">[1]</a></span>.</span></p>\n</blockquote>\n<h2>Nixpkgs</h2>\n<p><span>You may have noticed a reference to <code>nixpkgs</code> in the above derivation. As every input\nto a Nix derivation also has to be a Nix derivation, one can imagine the\ntedium involved in creating a Nix derivation for every dependency of\nyour project. However, Nixpkgs<a href=\"#fn3\">3</a> is a large repository of\nsoftware packaged in Nix, where a package is a Nix derivation. We can\nuse packages from Nixpkgs as inputs to a Nix derivation, as we’ve done\nwith <code>bash</code>.</span></p>\n<p><span>There is also a command line package\nmanager installing packages from Nixpkgs, which is why people often\nrefer to Nix as a package manager. While Nix, and therefore Nix package\nmanagement, is primarily source-based (since derivations describe how to\nbuild software from source), binary deployment is an optimisation of\nthis. Since packages are built in isolation and entirely determined by\ntheir inputs, binaries can be transparently deployed by downloading them\nfrom a remote server instead of building the derivation\nlocally.</span></p>\n\n\n<img src=\"./images/nixpkgs.png\">\n\nVisualisation of Nixpkgs<a href=\"#fn4\">4</a>\n\n<h2>NixOS</h2>\n<p><span>NixOS<a href=\"#fn5\">5</a> is a Linux distribution\nbuilt with Nix from a modular, purely functional specification <span><a href=\"#ref-dolstraNixOSPurelyFunctional2008\">[2]</a></span>. It has no traditional filesystem\nhierarchy (FSH), like <code>/bin</code>, <code>/lib</code>, <code>/usr</code>, but\ninstead stores all components in <code>/nix/store</code>. The system configuration is managed\nby Nix and configured with Nix expressions. NixOS modules are Nix files\ncontaining chunks of system configuration that can be composed to build\na full NixOS system<a href=\"#fn6\">6</a>. While many NixOS modules are\nprovided in the Nixpkgs repository, they can also be written by an\nindividual user. For example, the expression used to deploy a DNS server\nis a NixOS module. Together these modules form the configuration which\nbuilds the Linux system as a Nix derivation.</span></p>\n<p><span>NixOS minimises global mutable state that –\nwithout knowing it – you might rely on being set up in a certain way.\nFor example, you might follow instructions to run a series of shell\ncommands and edit some files to get a piece of software working. You may\nsubsequently be unable to reproduce the result because you’ve forgotten\nsome intricacy or are now using a different version of the software. Nix\nforces you to encode this in a reproducible way, which is extremely\nuseful for replicating software configurations and deployments, aiming\nto solve the ‘It works on my machine’ problem. Docker is often used to\nfix this configuration problem, but Nix aims to be more reproducible.\nThis can be frustrating at times because it can make it harder to get a\nproject off the ground, but I’ve found the benefits outweigh the\ndownsides, personally.</span></p>\n<p><span>My own NixOS configuration is publicly\navailable<a href=\"#fn7\">7</a>. This makes it simple to reproduce\nmy system (a collection of various hacks, scripts, and workarounds) on\nanother machine. I use it to manage servers, workstations, and more.\nCompared to my previous approach of maintaining a Git repository of\n<code>dotfiles</code>, this is much more modular,\nreproducible, and flexible. And if you want to deploy some new piece of\nsoftware or service, it can be as easy as changing a single line in your\nsystem configuration.</span></p>\n<p><span>Despite these advantages, the reason I\nswitched to NixOS from Arch Linux was simpler: NixOS allows rollbacks\nand atomic upgrades. As Arch packages bleeding-edge software with\nrolling updates, it would frequently happen that some new version of\nsomething I was using would break. Arch has one global coherent package\nset, so to avoid complications with solving dependency versions Arch\ndoesn’t support partial upgrades. Given this, the options were to wait\nfor the bug to be fixed or manually rollback all the updated packages by\ninspecting the <code>pacman</code> log (the Arch\npackage manager) and reinstalling the old versions from the local cache.\nWhile there may be tools on top of <code>pacman</code>\nto improve this, the straw that broke the camel’s back was when my\nmachine crashed while updating the Linux kernel, and I had to reinstall\nit from a live USB.</span></p>\n<p><span>While Nixpkgs also has one global coherent\npackage set, one can use multiple instances of Nixpkgs (i.e., channels)\nat once to support partial upgrades, as the Nix store allows multiple\nversions of a dependency to be stored. This also supports atomic\nupgrades, as all the software’s old versions can be kept until garbage\ncollection. The pointers to the new packages are only updated when the\ninstallation succeeds, so the crash during the Linux kernel upgrade\nwould not have broken my OS install on NixOS. And every new system\nconfiguration creates a GRUB entry, so you can boot previous systems\neven from your UEFI/BIOS.</span></p>\n<p><span>To summarise the parts of the Nix ecosystem\nthat we’ve discussed:</span></p>\n<p><img src=\"./images/nix-stack.svg\"></p>\n<h2>Flakes</h2>\n<p><span>Without going into too much depth, Flakes\nenable hermetic evaluation of Nix expressions and provide a standard way\nto compose Nix projects. With flakes, instead of using a Nixpkgs\nrepository version from a ‘channel’<a href=\"#fn8\">8</a>, we pin Nixpkgs as an\ninput to every Nix flake, be it a project build with Nix or a NixOS\nsystem. Integrated with flakes, there is also a new <code>nix</code> command aimed at improving the UI of Nix.\nYou can read more detail about flakes in a series of blog posts by Eelco\non the topic<a href=\"#fn9\">9</a>.</span></p>\n<h2>References</h2>\n<p><span><span></span></span></p>\n<div>\n<div>\n<span><div>[1] </div><div>E. Dolstra, M. de Jonge, and E. Visser,\n<span>“Nix: <span>A Safe</span> and <span>Policy-Free System</span> for\n<span>Software Deployment</span>,”</span> p. 14, 2004. </div></span>\n</div>\n<div>\n<span><div>[2] </div><div>E. Dolstra and A. Löh,\n<span>“<span>NixOS</span>: A purely functional <span>Linux</span>\ndistribution,”</span> <em>SIGPLAN Not.</em>, vol. 43, no. 9, pp.\n367–378, Sep. 2008, doi: <a href=\"https://doi.org/10.1145/1411203.1411255\">10.1145/1411203.1411255</a>.\n[Online]. Available: <a href=\"https://doi.org/10.1145/1411203.1411255\">https://doi.org/10.1145/1411203.1411255</a>.\n[Accessed: Oct. 13, 2022]</div></span>\n</div>\n</div>\n\n\n\n\n<ol>\n<li><p><span>As ‘nix’ means snow in Latin. Credits\nto Tim Cuthbertson.</span><a href=\"#fnref1\">↩︎</a></p></li>\n<li><p><span>NB: we will use component, dependency,\nand package somewhat interchangeably in this blog post, as they all\nfundamentally mean the same thing – a piece of software.</span><a href=\"#fnref2\">↩︎</a></p></li>\n<li><p><span><a href=\"https://github.com/nixos/nixpkgs\">github.com/nixos/nixpkgs</a></span><a href=\"#fnref3\">↩︎</a></p></li>\n<li><p><span><a href=\"https://www.tweag.io/blog/2022-09-13-nixpkgs-graph/\">www.tweag.io<em>blog/2022-09-13-nixpkgs-graph</em></a></span><a href=\"#fnref4\">↩︎</a></p></li>\n<li><p><span><a href=\"https://nixos.org\">nixos.org</a></span><a href=\"#fnref5\">↩︎</a></p></li>\n<li><p><span><a href=\"https://nixos.org/manual/nixos/stable/index.html#sec-writing-modules\">NixOS\nmanual Chapter 66. Writing NixOS Modules</a>.</span><a href=\"#fnref6\">↩︎</a></p></li>\n<li><p><span><a href=\"https://github.com/RyanGibb/nixos\">github.com/RyanGibb/nixos</a></span><a href=\"#fnref7\">↩︎</a></p></li>\n<li><p><span><a href=\"https://nixos.org/manual/nix/stable/package-management/channels.html\">nixos.org/manual/nix/stable/package-management/channels.html</a></span><a href=\"#fnref8\">↩︎</a></p></li>\n<li><p><span><a href=\"https://www.tweag.io/blog/2020-05-25-flakes/\">tweag.io/blog/2020-05-25-flakes</a></span><a href=\"#fnref9\">↩︎</a></p></li>\n</ol>",
9 "content_type": "html",
10 "categories": [],
11 "source": "https://ryan.freumh.org/atom.xml"
12}