Switching to NixOS on my Desktop
Published: 2020-11-03 12:42:00

---
title: Switching to NixOS on my Desktop
published: true
date: 2020-09-06 13:20:00 UTC
tags: 
canonical_url: https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/
---

<main><p>I’ve been a long time Linux user, and most of that time was spent on <a href="https://www.archlinux.org/">Arch Linux</a>. I am a huge fan of Arch, some of my favourite features are the following:</p>

<ol>
  <li>Very vanilla. Packages are rarely modified from upstream. This is nice because I get what the upstream intended and it is easy to report bugs. This is <a href="https://kevincox.ca/2013/01/30/thoughts-on-ubuntu">one of the original reasons I switched to Arch</a> and I still value this feature.</li>
  <li>Up to date. Packages in Arch usually follow upstream releases quite closely. This is nice both because you an get the latest features and improvement and using the latest version also helps when reporting issues upstream.</li>
  <li>Forever supported. I installed Arch when I first got my laptop about 5 years ago and haven’t needed to do anything but update since then. (Well you need to read the <a href="https://www.archlinux.org/news/">news</a>, but usually you can just look at the most recent post retroactively when an update fails). 5 years is within the time frame of some <a href="https://en.wikipedia.org/wiki/Long-term_support">LTS</a> distros but for most of those distros most people will recommend that you reinstall rather than upgrade between LTS versions, even if it is supported.</li>
</ol>

<p>From my experience up to date packages (2) won’t be much of an issue, and if I am in a hurry I can usually submit version bumps myself. I can also use a <a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#patches">custom package definition</a> if I need the new version right now. Forever supported (3) won’t be an issue because you really never “update” NixOS, you are logically installing from scratch every time you apply your configuration. Vanilla packages (1) may be a bit of a problem since many packages need patches to run on a “weird” distribution such as NixOS. Only more experience will let me know if these have the same kind of annoyances as the Ubuntu patches or if the fact that they are usually constrained to finding dependencies means they will not cause the same kind of issues.</p>

<p>I’ve been using NixOS <a href="https://kevincox.ca/2015/12/21/service-management-with-nixos">on servers</a> and to <a href="https://gitlab.com/kevincox/dontsayit-api/-/blob/master/default.nix">build docker images</a> for quite a while. Looking into my personal nix configs repo I committed the README in October 2015. I first starting managing some servers with Nix, running a distributed scheduler to run software that I built and distributed with Nix. Later when I got a home server NixOS was the obvious choice. I’ve been very happy with Nix but didn’t know how well the graphical desktop environment setup worked, but after some experimenting in a VM I decided that it was good enough to take the plunge.</p>

<p>The main features that pulled me to NixOS were:</p>

<ol>
  <li>Ability to easily patch packages. While you could download the <a href="https://wiki.archlinux.org/index.php/PKGBUILD">PKGBUILD</a> for an Arch package and modify it, it was no longer part of your regular update process. You need to remember to rebuild these packages regularly, and possibly rebase onto the newest PKGBUILD</li>
  <li>Ability to trivially rollback the system configuration. With just about any distro you will have the occasional bad update. With Arch I was <a href="https://gitlab.com/-/snippets/1952423">grepping the update log and installing the older packages</a>. Filesystem snapshots can make this more elegant but it can be difficult to separate the system from the state that shouldn’t be rolled back.</li>
  <li>Reproducibility. With Arch I realized that my system was slowly accumulating small tweaks and changes that were almost impossible to track. This slowly increasing deviation away from an unmodified install will surely cause trouble eventually. Furthermore I have been considering getting a new computer for a while now and unless I just clone the disk I know that it will be a pain to copy all of these changes over. Especially if I end up using multiple devices regularly and want to keep the configurations mostly in sync.</li>
</ol>

<h2 id="installing-nixos"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#installing-nixos">Installing NixOS</a></h2>

<p>I had an auto-installer script from when I installed my home server. I cleaned it up and used it again. I have since updated it to run completely offline and have published it at <a href="https://gitlab.com/kevincox/nixos-auto-install">https://gitlab.com/kevincox/nixos-auto-install</a>.</p>

<p>I simply built the ISO, put it on a USB, booted off of it and after a lot of copying my device rebooted into NixOS. I then downloaded the configuration I was using in my test VM and rebuilt the system from that. All that was left was setting a password for the disk encryption.</p>

<h2 id="configuring"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#configuring">Configuring</a></h2>

<p>Once I had my working system I just tweaked to my liking. I merged my desktop and existing server configuration that included a number of things such as useful packages to have available at the command line and basic configurations for zsh, vim and similar. Overall nothing about this configuration is too exciting. Most things worked as expected and I got the <a href="https://nixos.wiki/wiki/GNOME">GNOME</a>+Wayland environment that I wanted. I’ll show a couple of the more interesting snippets here.</p>

<h3 id="patches"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#patches">Patches</a></h3>

<p>Changing package versions, build flags or adding patches is super easy. Here are two examples. For libinput I am using the tip commit of an open MR, pinning the version. For vte I’m just applying a patch on top of whatever version is in nixpkgs. You can easily combine these together or tweak other package settings. I also have a simple helper function to make the common action of adding an additional patch extra easy although even the full version (below) isn’t too bad.</p>

<div><pre><code><span>nixpkgs</span><span>.</span><span>config</span><span>.</span><span>packageOverrides</span> <span>=</span> <span>pkgs</span><span>:</span> <span>rec</span> <span>{</span>
	<span># Trying out an experimental branch of libinput.</span>
	<span>libinput</span> <span>=</span> <span>pkgs</span><span>.</span><span>libinput</span><span>.</span><span>overrideAttrs</span> <span>(</span><span>attrs</span><span>:</span> <span>{</span>
		<span>src</span> <span>=</span> <span>pkgs</span><span>.</span><span>fetchFromGitLab</span> <span>{</span>
			<span>domain</span> <span>=</span> <span>"gitlab.freedesktop.org"</span><span>;</span>
			<span>owner</span> <span>=</span> <span>"libinput"</span><span>;</span>
			<span>repo</span> <span>=</span> <span>"libinput"</span><span>;</span>
			<span>rev</span> <span>=</span> <span>"4293804898fad6175ee9e5ceafe234695393cc09"</span><span>;</span>
			<span>hash</span> <span>=</span> <span>"sha256:1mzwwjf34k8vxcjmw4m2v7g5d0vr9kd0i57d9ynmjmc7wpipxrq4"</span><span>;</span>
		<span>};</span>
	<span>});</span>

	<span># Applying a patch to the current version of vte.</span>
	<span>vte</span> <span>=</span> <span>pkgs</span><span>.</span><span>vte</span><span>.</span><span>overrideAttrs</span> <span>(</span><span>attrs</span><span>:</span> <span>{</span>
		<span>patches</span> <span>=</span> <span>(</span><span>attrs</span><span>.</span><span>patches</span> <span>or</span> <span>[])</span> <span>++</span> <span>[</span>
			<span>pkgs</span><span>.</span><span>fetchpatch</span> <span>{</span>
				<span>name</span> <span>=</span> <span>"cntnr-precmd-preexec-scroll.patch"</span><span>;</span>
				<span>url</span> <span>=</span> <span>"https://src.fedoraproject.org/rpms/vte291/raw/89a86276e6652c6c48fc1b7b8ab724e0cf0ee0fb/f/vte291-cntnr-precmd-preexec-scroll.patch"</span><span>;</span>
				<span>sha256</span> <span>=</span> <span>"1cwnj6gqwn05d53indlcsnmw4z39hlizzxm0nwl78madciz2vcag"</span><span>;</span>
			<span>}</span>
		<span>];</span>
	<span>});</span>
<span>};</span>
</code></pre></div>
<h3 id="other-options"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#other-options">Other options</a></h3>

<p>Now my entire system is defined in a handful of config files and the defaults provided by NixOS. This means that I can easily audit my local changes and ensure that old changes aren’t being carried around over time. NixOS provides the primatives to write config files or run services but often the options you need are already wrapped up in easy to use modules such as GnuPG.</p>

<div><pre><code><span>programs</span><span>.</span><span>gnupg</span><span>.</span><span>agent</span> <span>=</span> <span>{</span>
	<span>enable</span> <span>=</span> <span>true</span><span>;</span>
	<span>enableSSHSupport</span> <span>=</span> <span>true</span><span>;</span>
	<span>pinentryFlavor</span> <span>=</span> <span>"gnome3"</span><span>;</span>
<span>};</span>
</code></pre></div>
<p>This higher-level configuration is also very convenient as it allows modules to configure each other when required. So for example enabling the GPaste can automatically add the extension to GNOME Extension.</p>

<h2 id="hackability"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#hackability">Hackability</a></h2>

<p><a href="https://github.com/NixOS/nixpkgs/">nixpkgs</a> (where NixOS and all of the Nix packages are defined) is very open to contributions. You can simply open a PR and most simple changes like adding a package or bumping a version will be merged in a couple of days. It is also very easy to use your own modifications before they are merged and to pull in package definitions or modules from the community making it very hacker friendly.</p>

<h2 id="nixos-rebuild-build-vm"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#nixos-rebuild-build-vm">nixos-rebuild build-vm</a></h2>

<p>The nice thing about the declarative configuration is that it is easy to recreate your setup. For example you can easily test your configuration on a test system and be quite sure that it will work correctly on your regular machine. While the ability to easily boot into known-good configurations from the bootloader means that testing on a different system isn’t necessary as it is very unlikely that you brick your install, rebooting after every change slows down iteration. In many cases a reboot isn’t necessary and <code>nixos-rebuild switch</code> can be used. However if you are making change to environment variables, display manager manager or something similar that you can’t restart you can use the <code>nixos-rebuild build-vm</code> command which builds your configuration into a VM (which shares the Nix store with your host so it is very quick to build). Then you can just run the generated script and test your new configuration without closing your editor. The next time you are trying out patches to your window manager or desktop environment you will be incredibly thankful about this feature.</p>

<h2 id="conclusion"><a href="https://kevincox.ca/2020/09/06/switching-to-desktop-nixos/#conclusion">Conclusion</a></h2>

<p>I’m very happy with my setup, even though I have only been using it for a week I think it will last me a long time. I would recommend NixOS to anyone who is interested in tweaking some parts of their desktop, but for the most part wants to set it and forget it.</p>