Two weeks ago, I found myself with a new desktop PC and a world of possibilities. And of that whole world of options, I chose NixOS. Not to brag, but I am a burgeoning script kiddie: a few months ago I made the switch from the default MacOS Terminal to Kitty, from VS Code to Neovim, and from Finder to lf. I can cat and grep and have a handful of zsh aliases, so installing NixOS shouldn’t be too hard, right? Right?

NixOS, from my point of view

My first exposure to NixOS came via neovim via dotfiles. Neovim is incredibly configurable, and people have spent years of their lives ensuring that the key binds and color schemes and plugins are just right. Those same people also appreciate the importance of backups, and so their neovim configuration files get pushed into their own Github repositories. “Wonderful!” they said, “now I can just clone my neovim config repo and take my own, personal neovim wherever I go!” But then they were confronted with one of the horrors of reality: neovim is not the only program on one’s computer! It’s not even the only configurable program on one’s computer!

Enter dotfiles. In your computer’s ~/.config directory are dozens of files and directories that tell other programs how to set themselves up. These files and directories often start with a ., hence dotfiles. Some programs, like Hyprland window manager, have their own config languages. Others, like Github, use existing formats like yaml or json. Sometimes a program only lets its colors get changed; others let config files isntall and manage plugins and set up other advanced behaviors. People have spent decades getting their programs configured just right. Those same people also appreciate the importance of backups, and so their entire ~/.config directories get pushed into their own github repositories.

dotfiles locally and dotfiles in git are not the same

“Wonderful!” they said, “now I can just clone my dotfiles repo and take all my program configurations wherever I go!” But then they were confronted by not one, but two separate horrors of reality: 1. One still has to install all those programs first before they can be configured 2. There are settings at the operating-system-level that aren’t configured in ~/.config

NixOS was introduced to me as a retort to horrific reality: “It’s like dotfiles but for your whole computer!” And, since I had been spending way too much time on github browsing through other peoples’ dotfiles repos in order to steal things for my own dotfiles, I was both thoroughly dotfiles-pilled and thoroughly intrigued. At that same time, I was also cautioned: “Nix has a really steep learning curve, though.”

yeah the learning curve is kinda steep

Attempt #0

To be completely fair to the NixOS people, actually installing NixOS was no different and no more difficult than installing any other Linux distro: * I went out and bought a cheap USB drive * I downloaded an .iso from the NixOS website and burned it to the USB * I plugged the USB into my new machine, booted into it, and ran the installer

After a quick reboot, I was now running the default NixOS! Mission accomplished, right?

one does not simply use default nixos configuration

This is where NixOS’s unique brand of neuroticism comes into play. As “dotfiles for your whole computer,” NixOS lets you declare everything about your computer so that, as soon as it boots up, it is perfectly tweaked and tuned to be how you like it. So users are encouraged - nay, oblidged - to go into a file called congfiguration.nix and go crazy. How crazy? Well, you can define: * Your users - names, permissions, and temporary passwords * Your programs - both system-level programs and user-level programs, and the configurations for those programs * Your drivers * Your desktop environment and its settings * Your window manager and its settings * Your boot loader and its settings

Attempt #1

That sure is a lot of options to configure! So, like any programmer, I started to look at how other people built their Nix configurations so that I could ~study and understand nix~ steal from them for an easy win. I watched this video from Vimjoyer on YouTube and also copied their repo. They also took a lot from Misterio77’s repo so I borrowed a few things from them as well. These repos not only used baseline Nix, but also two Nix-adjacent tools called Flakes and Home-Manager. Needless to say, these projects are complicated and have a lot of stuff, so I decided to just pick and choose the bits that I wanted.

I took the directory structure from Vimjoyer, the flake setup from Misterio77, and used a variation of the default home-manager config. I removed half the programs that Vimjoyer declared because I don’t need them, and then added a few of my own. After about half and hour of playing picky-choosy, I run my first system rebuild, and get…

error: The optionhome-manager.users.gordy.environment does not exist.

…an inscrutable error message. RIP Attempt #1.

I don't have a picture of that error message so you get this meme instead

Attempt #2

Well, time to dig in! I googled, I browsed the NixOS Discourse and Discord, and started learning a few things about NixOS: * There are two Nix wikis - nixos.wiki (BAD!) and wiki.nixos.org (GOOD!), and also two nix websites with manuals - nix.dev (BAD!) and nix.org (GOOD!) * Home Manager and Flakes have a weird relationship that causes awful error messages * NixOS’s configuration.nix, flakes’ flake.nix, and home manager’s home.nix all do this dance together but I don’t get it yet * You can break your configuration.nix file into multiple, smaller files, but there is a different trick to make them all play along together.

After a couple hours trying to debug and get good, I decided to throw in the towel. This was just too much too soon, and I couldn’t understand enough to make meaningful progress.

All of this lead me to conclude three things. 1. Starting with a complex configuration is a bad way to learn 2. This configuration is too complex for me 3. I need to do something simpler

100% real image of me reading the wrong nix wiki

Attempt #3

This time, I deleted everything frim Vimjoyer and started with a fresh directory. I laid out my configuration.nix, my flake.nix, and my home.nix like I was setting up a chess board. Then I started modifying the contents using examples from their respective wikis and resources. I rebuilt the system and it didn’t crash! Then I rebuilt it again and got a new error: Out of Disk Storage. Huh?

My machine has a 4 TB SSD, so there is plenty of space for Nix; however, I installed Nix on a boot partition that was only 32 GB. And while I thought that nix would put all of its system files in the other partition, it was actually filling up its tiny boot partition. Despite how configurable Nix is, there isn’t a configuration to move its system files (the nix store) off of /boot. And this partition was so full that I could not even run operations to delete older generations. RIP

what my GNOME drive manager looked like at the time

Attempt #4

Once again, I installed from my boot drive and used the same tiny partitions as before. Yes I should have fixed it at this point, but I was convinced that I’d just remember to not keep more than 2 or 3 old generations around at a time! Easy!

So I copied the same configuration.nix, flake.nix, and home.nix settings from earlier and began making changes. I also resolved to be better about deleting older generations before making new ones.

While configuring my user space, I remembered from a basic cybersecurity training long ago that the regular user account should not be a root account, so I configured the user gordy to not have sudo access. And one quick rebuild later, I could no longer edit any of my .nix files, since they were in /etc/ and locked behind root privlidges. Nor could I rebuild the system, as the command was sudo nixos-rebuild.

sudo is required to rebuild and switch NixOS generations

Attempts #5 and #6

Realizing the error of my ways, I resolved myself once more to persue simplicity by preparing a 100GB partition for NixOS so that I could keep more old generations around. However this new boot partition was ext4, while NixOS required fat32 format for boot drives. So instead, I tried to just expand my smaller, existing boot partition, but that ended up just deleting the existing NixOS installation somehow. Whoops! I ended up trying this process twice just to make sure it was the error I thought it was, and not something else.

Attempt #7

This time, I decided to just wipe all the existing partitions and reformat the all 3.8TB of available storage as a generic “NixOS partition.” And it worked out great! Now, I was able to actually start configuring NixOS, starting with the graphics drivers.

My machine has an Nvidia 4060, so I had to go through the usual Linux song and dance with Nvidia and their closed-source drivers; however, NixOS was actually making this whole process easier than expected! It was actually really nice to have a baseline “stable” generation that used whatever driver NixOS shipped with, and then make experimental generations using the different Nvidia graphics drivers. When those other graphics drivers failed to start, or caused awful flickering– no problem! I’ll just boot back into my stable generation and try again!

was nix being beneficial? Also how do you spell nickel?

At this point, I wasn’t just experimenting, I felt like I was learning! And one such thing I learned from previous attempts was: Don’t let too many old generations build up and take all your storage space! Yes, my partition had 3.8 TB now, but good habits need to start somewhere! So I looked up on the wiki how to delete old generations and found this command:

nix-collect-garbage -d

I ran it, and presto! No more older generations! I quickly changed to an unstable graphics driver, tested it, and then my stomach dropped: There was only one generation now. I had deleted my stable generation! And what’s worse- the graphics driver I switched to doesn’t even show TTY! With a heavy heart, I reinstalled the OS and began again.

me, destroying my setup in real time

Attempt #8

Throughout this whole ordeal, I kept a notepad on my desk with notes, commands, and processes written down. This was super helpful for things like: * Context switching - there is a lot of hurry upand wait, so I do other stuff. But then when I come back, or after I complete a step, the instructions eliminate that “uhhhh what now?” feeling * A copy of what’s on the computer - While dealing with all the system crashes, it was really handy to have a refrence of what was supposed to be in the config. * A record of things tried

an actual picture of my notepad

Thanks largely to these notes, I was back to where attempt #7 left off after only 2 rebuilds! The final task before me is (still) getting the right Nvidia driver up and running. I quickly got into a rhythm trying a different driver version, or different settings in my configuration.nix, but each trial ended up with the same result:

My desktop setup, with blank screens

The monitors were both completely blank. One of them intentionally so; without a graphics driver, signal was only being sent to the primary monitor. In order to avoid getting interrupted by a blinking No Signal splash screen on my second monitor, I turned it off. But then, on a whim, after the 10th or 11th combination of graphics driver and settings, I turned it on and saw the GNOME login prompt!

Turns out, the “primary monitor” got switched during the graphics driver update, and it was now outputting to th vertical monitor, which was powered off. Who knows how much time I could have saved if I had just kept both monitors on, or unplugged the HDMI cable from the secondary monitor? It still hurts me to think about, but it has taught me a lesson about there always being a simpler setup.

I quickly installed Hyprland, my preferred window manager, and was able to boot into the environment from TTY; however, in my zeal for Hyprland, I abandoned GNOME desktop too quickly. It turns out that the GTK libraries that power the GNOME desktop are also relied upon by Hyprland for critical things like keyboard input and bluetooth connections. As someone using a bluetooth keyboard, removing GTK was, in short, a bad idea, and made it impossible for me to use my keyboard or any other input devices.

After deleting the library that made keyboard input possible, I felt like a clown

Attempt #9

Thanks to my notebook, I had enough documentation to get back to where I was in attempt #8 rather quickly. And soon enough I was able to make Hyprland the default desktop environment, even though GNOME was still there in the background, managing essential services.

This was my first successful build and install. Although my personal customization had yet to begin in earnest, I could cross off a few key milestones: * I had installed NixOS * I had installed and loaded the correct NVidia graphic driver * I had installed and run Hyprland

And with these criteria met, I declared my first Nix task finished. Next up was the fun part: installing and configuring my applications!

One of the default hyprland wallpapers is this anime girl

Where to go from here?

These first 9 attempts taught me most about: 1. The importance of documentation! Making notes about your process not only helps you avoid repeating your own mistakes, but the act of writing things down is part of the learning process. I genuinely learn faster when I’m taking notes. 2. Start with the simplist setup you can, then make it simpler. One of the NixOS wikis says something like:

> Beginners are advised to start with simple setup first, and only add features as needs arise

and that is some wisdom right there. I started with ideas and complexity way beyond what I needed, and sunk too much time into understanding a system that wasn’t right for me rather than building one that was.

how it felt upon that first boot into hyprland

The forced downtime while re-installing the operating system gave me a lot of time to think about what it is that I want from my computer. It narrows down to three things:

1. Learn to dance with my computer, not just use it

I’m on a computer for 10+ hours a day, yet there is so much I don’t know or don’t take advantage of when it comes to my computers! When you watch someone like The Primeagean use their machines, they execute at the speed of thought, and I want to do that, too! So “dancing” with my computer, to me, means: * Being highly competant with a small handful of useful programs * Having the dexterity and muscle memory to type quickly and accurately, and leverage keybinds over the mouse wherever possible * Configuring my computer so such a degree that it becomes an extension of my own self

2. Elevate my computer beyond the limits of its physical form

The underlying philosophy of NixOS really resonates with me. My Macbook is a singular, unique object: if it blew up, or I got a replacement of the same model, it would be completely impossible to reproduce what was my machine. Since the previous goal is to make my computer an extension of my own self, it makes sense that such an extension should be backed up and kept safe in the best way possible. To me, this means: * Leveraging Nix to declare as much of my system as I can * Backing up all my configurations and dotfiles * Synchronizing personal files with an offsite backup

3. Make my computer pretty, inside and out

Since I spend so much time on a computer, it is worthwhile to make my computer a beautiful place to spend time in. A nice thing about Linux being so configurable is that I can decide exactly how I want the aesthetic design to be, and change it as I see fit. There is also an entire world of Linux ricing out there, and that community maintains some incredible tools. Beauty also extends to the software: I want the way I declare my computer to be beautiful, too! So my persuits of beauty can be summarized as: * Unifying my apps under a single aesthetic that I like * Structuring my Nix and dotfiles directories in simple modules * Leverage software like Hyprland that support this kind of aesthetic persuit.

ChatGPT illustrated my goals

So that’s just what I’ll be doing in the coming months and years. See y’all in the next one!

❤️ Gordy