Today I write about how I managed to install a custom login manager theme on NixOS, and my journey in trying to understand NixOS a little bit more.
SDDM, the Simple Desktop Display Manager is a popular login screen manager for Linux. Unfortunately, with my little experience with NixOS, I’ve had a fair few issues with SDDM. In particular, installing themes for SDDM.
In my previous blog post, Overcoming NixOS Problems, I wrote about how I overcame this issue by adding
nix.readOnlyStore = false; to my
configuration.nix file. Unfortunately, after the events of re-installing my operating system because I installed another version of Qt and wiping my boot partition, my
configuration.nix file alone was not enough to install the login theme that I wanted. I ended up learning the hard way that
nix.readOnlyStore = false; is not a proper solution, because it’s “impure” (It’s not entirely deterministic on its own).
So I have to find some other way to install this SDDM theme. In order to do that “the Nix way”, I have to learn the Nix programming language. “Not a problem” I think to myself; “How hard can it be?”. I go to the good ol’ reliable source of all information “Google” and search for “Nix”. Aha! The Nix manual!
Now, this may sound like I just discovered the one stop solution to all of my problems, but unfortunately, all I discovered was the one stop problem to all of my problems.
The Nix manual contents page alone is the most daunting thing that I have seen to date. I browse the contents and find the section I want - Writing Nix Expressions - Chapter 14. I follow the manual paragraph by paragraph until it has a giant chunk of code, with explanations for each line. “So and so is a derivation”; “So and so is an attribute”; “So and so is a derivation builder”; “So and so is a shorthand for
perl = perl;, because that looks stupid on its own”…
It was evident to me that this Nix manual is definitely not going to help me. After a little more digging online, I discover the Nix Pills, which are a series of blog posts written by Luca Bruno, that were ported over to the Nix website because they’re so good at explaining Nix and are a suitable introduction for newcomers. And true enough, it seems to be somewhat more comprehensible than the Nix Manual.
It begins with simple Nix expressions, declaring functions, importing files and by the fifth “pill”, it describes how to create a derivation. At this point, I am already being completely overwhelmed with information and derivations are going straight over my head.
Three weeks later, I end up writing my first derivation, the thing that solves all of my problems.
Now, if I had paid attention to the NixOS about page, I would have probably read the section called “How does NixOS work?”. It just so happens that this section explains something that I’ve been trying to comprehend for the past three weeks. It basically states the following:
NixOS does not store packages in
/usretc. - all packages are kept in
What this means for me is that I cannot simply create files in
/usr/share/sddm/themes/, which is where SDDM themes normally lie. Instead, I have to create a derivation, which stores a theme file in
/nix/store/<<my_derivation>>/share/sddm/themes/<<my_theme>>. If only I knew this from the very beginning, that would make my life so much easier.
The idea of writing my first derivation came to mind after I saw how simple the derivation for i3lock-fancy (a program that makes i3lock (a lock screen manager) look fancy) was put together. It consists of a simple “fetchFromGitHub” function, an “installPhase” and what looked like an optional “patch phase”. Surely, if I can download the software I need from GitHub, I can just copy it into the correct directories and it’ll work, right?
Firstly, I have to fetch code from GitHub. The
fetchFromGitHub function is (like a lot of Nix things) very poorly documented, so I decide to just use what I could from the build script from i3lock-fancy. The function seems to take in 4 parameters: The owner of a GitHub repository, the name of the repository, a thing called “rev” and a sha256 hash of the file which is to be downloaded.
I begin by writing out the owner and name of the repository and discover that rev refers to the GitHub commit hash (known as a revision I guess?). Luckily, this isn’t very difficult to find, you just click the latest commit and the hash is somewhere to be found on GitHub’s webpage. Now all I have to do is find the hash.
I download the code for the specific rev that I want by browsing GitHub’s page, navigating to the correct tree for that specific commit and press “Download zip”. I then pass that through the
nix-hash command (yes, Nix has their own hashing command) with the generic arguments (as I previously read in some documentation somewhere)
--base32 --type sha256. Unfortunately, when I supply this hash to the derivation, it fails because it’s the wrong hash. If I can’t figure out the correct hash, how am I going to download a project from GitHub?
And then it hits me. The console output from the failed derivation says what the hash is supposed to be. So, by means of hacky coding, I supply that hash and surprise surprise, it just works. I’ve been able to download some code from GitHub.
After being able to download the code from GitHub, writing the rest of the derivation was trivial. Make the folder
/share/sddm/themes/clairvoyance (Because the SDDM theme is called “clairvoyance”) and show all of the contents from the GitHub project into that folder. I import the code into my
configuration.nix file under the system packages, then I run
sudo nixos-rebuild switch and watch as my derivation is brought to life. I close my i3 tiling manager (I log out) and I see that the sddm theme is properly loaded.
Honestly, despite the difficulties and steep learning curve, once you’ve managed to create a derivation once, it becomes easier to apply what you’ve learnt to future projects.
As a random guy on the internet once said, “It’s easy when you know how”.