Why I Left NixOS for Ubuntu
Posted on Thu 02 May 2024 in general
If you've hung out in Linux enthusiast circles lately, you'll have heard whispers that Arch Linux is no longer hot product. Instead, all the cool kids are using something called NixOS.
Since I bricked my Debian setup in an unfortunate accident involving compiling from source, I decided to give NixOS a try. However, after hitting rock bottom and waking up, coldly sweating, in a darkened apartment surrounded by printouts of configuration.nix
, I decided to return to the warm and wholesome embrace of Ubuntu.
Why I Used NixOS
It can be hard to understand the attraction of NixOS if you haven't had some exposure to infrastructure or system administration before.
NixOS offers a unique set of features which make it very attractive from a system operator or power user perspective. These are largely based around avoiding issues which plague other Linux distributions.
Declarative Syntax and Reproducibility
Unlike most Linux distributions, NixOS's package manager is not primarily designed to pull down binaries from a repository. It's designed to create reproducible setups in a series of plaintext .nix
files, starting with configuration.nix
.
In configuration.nix
you'll find options that in other distributions are hidden away in murky utilities or config files. For example, which mode should a system's graphics card be set to? Should CUDA be enabled on this system? Do we want to have Wayland, X, or both as our display server?
You can also install programs and system utilities this way. By adding them to configuration.nix
and running nixos-rebuild switch
you rebuild your current system configuration and add it as a new boot option. Since NixOS is a static distribution, this is done without manipulating existing binaries or system settings, and can be rolled back at any time.
Rather than running an install utility, we use the Nix language to say what we want, and then tell nixos-rebuild
to make it so.
This means you can take a configuration.nix
file, give it to your friend, and they'll be able to easily reproduce your setup. This has made NixOS popular for ricing in some circles, as it allows entire desktop setups to be shared as a series of plaintext files - much easier than throwing VMs or complex setup scripts around the internet.
This is similar to the way Unix setups already handle config. Most Linux utilities, and a lot of MacOS ones, put their config files in the .config
folder for a given user. Since these files are just text, you can back them up easily, and pull them onto different systems if you switch computer.
Isolated Environments
Last time I bricked Debian, it was by creating dependency hell.
Dependency hell is a situation where two different pieces of software use different and incompatible versions of the same library. For example, App A uses libga 1.3
while App B uses libga 2.1
. We can't install both versions of libga
at the same time. Therefore we can't use App A and App B at the same time.
This happens a lot when you need to install packages from binaries or compile from source. On Debian, this situation comes up often: most projects choose to support Ubuntu rather than Debian, and the common workaround is just to supply the source code or a .deb
binary.
One of the unique features of NixOS is its adherence to isolated, immutable environments for different apps, including the dependencies of a package. This means that unlike with other distributions, especially Debian-based distros, you almost never run into dependency hell.
Instead, Nix will simply install both dependencies and link the applications to different versions. This simply isn't possible on most distros without using a container runtime like Flatpak or Snap.
This means that it's possible to run packages which are incompatible on NixOS without creating dependency hell. On most distros I find that my preferred image editor, Pinta, often breaks due to the GTK and LibMono versions available, but on NixOS it ran perfectly first time.
Isolated environments also make NixOS a lot more resilient to subtle issues which can break other Linux distros. For example, in Debian Sid (unstable branch), utilities often break for unspecified periods of time while their dependencies catch up. If you're unlucky enough to have one of those dependencies be something critical for your system -- say glibc
goes out of sync with nvidia-drivers
-- then you'll face a sudden system failure on update.
NixOS rarely has these issues. Since it's an immutable distribution, it also stores previous versions of the environment so you can roll back when you do encounter a system failure. On other distributions you need to use an extra utility like Timeshift for this.
Why I Left NixOS
Given the benefits of NixOS I outlined above, why'd I leave? Mostly, it was down to issues with everyday usage which don't happen on competing distributions.
Config Files are a Timesink
When configuration is done via text file, you have to manage those text files. Rather than a package manager like pacman
or apt
which handles most of the complicated stuff, NixOS makes the end user responsible for their own system configuration. This paradigm makes a lot of sense in a business and system administration context, but not so much in everyday desktop usage.
Often, configuration.nix
doesn't offer options that are part of the underlying binaries and there's not a clear way to access those options.
While I could write my own configuration files, or hack around with existing ones, this adds a time and maintenance burden that I don't want to deal with to use my daily driver.
This is the same problem that I found when I was daily driving nvim
-- I spent a lot of time playing with plugin options and wrastling my configuration, when I could have been working on more interesting and productive technical challenges.
The Downsides of Sandboxing
One of the languages I write most is Python. In Python, the normal way to separate project dependencies is to use a venv
. It's also common to use a few global tools like PyLsp or PyLance for linting and formatting.
NixOS's sandboxed model breaks many Python setups. venv
does not work correctly under NixOS, and global dependencies like PyLance also fail. This means that the main package manager for Python, pip
, is crippled on NixOS. There are Nix packages which replace many of the packages normally provided by pip, but as they're community contributed they are often out of date or slightly broken.
This problem isn't unique to Python. Common Linux utilities like GIMP and ffmpeg were challenging to configure for NixOS. Installing Nvidia's CUDA module even required NixOS to compile GIMP from source, which took two hours.
Less important than Python breaking, but still of concern to the desktop Linux enthusiast, is that GTK themes often break under NixOS. Not every application will correctly pick up custom themes and icons, and they sometimes require extensive configuration to pick up styles correctly.
I've experienced similar woes with other container runtimes like Snap and FlatPak. However, since NixOS is a fully sandboxed distribution, the general issues with isolated apps are much more prominent than when you're merely using a container runtime on a conventional distribution.
Nix's sandboxed model therefore works well in a server or workstation context, but for a general purpose desktop a more conventional distribution is probably more suitable.
Stability Oversold
As I mentioned above, Nix can have some issues with unusual configurations like CUDA and sometimes fails to correctly pick up environment variables correctly.
More serious than this is the rare occasions Nix packages conflict with each other. While Nix separates dependencies, it doesn't separate them as absolutely as a full container system like Docker. Therefore it is possible, albeit unlikely, to end up with conflicts between versions of installed libraries.
In the end this is what made me decide to leave Nix: I installed a new display manager and immediately broke my desktop setup. This wasn't helped by the inadequate support available online.
Lack of Support
The need to play with config files, fix stability issues and manage issues with configuration would be less of a drag if there were a NixOS resource comparable to the Arch Wiki. However, the community resources available for Nix are far more scarce than for Arch.
NixOS also follows a radically different paradigm to Arch or Debian, so you can't reuse the resources for those distros like you could on derivatives like Linux Mint or EndeavourOS.
Since Nix is a community distribution, it also doesn't have a corporate backer who can provide official support, unlike RHEL, SUSE, or Ubuntu.
The small community and lack of official support means that you're likely to spend a lot of time fixing issues yourself, reading documentation, and piecing together clues from various sources. This is fine if you're a technologist, but it's a major timesink.
Why Ubuntu?
Ubuntu is out of favor with Linux enthusiasts for a number of reasons. One of the main ones is good old-fashioned elitism: Ubuntu is known for being easy to use, and therefore has a reputation as a beginner distribution.
In the last few years Ubuntu has also been plagued with a number of controversies which have damaged its reputation compared to the halcyon days of yore.
For reasons of pride I almost went with an Ubuntu derivative or respin like Linux Mint or PopOS. I ran Mint for a couple of days before remembering why I moved away from it - Mint is an opinionated, complete experience which goes against a lot of what I enjoy about Linux. Meanwhile, PopOS is currently on a delayed release schedule due to the maintainers, System76, moving to a new desktop environment built in Rust.
I ran Debian, Ubuntu's parent distribution, for a long time and also considered moving back to that. However, Debian has some of the same issues as NixOS, especially lacking widespread support and requiring close attention to detail in system configuration. It also has generally worse driver support and fewer packages available to it due to a lack of PPAs (community repositories).
While many of the issues with Debian can be resolved by compiling from source, this has been one of the main causes of system failure for me in the past. It also requires equal or greater effort than playing with Nixfiles.
As a DIY distribution, Arch would have recreated my config file woes on a grand scale. I'm also not a huge Arch fan and dislike pacman
as a package manager.
With all these considerations in mind, and not wanting to move to unfamiliar distributions like Fedora or OpenSUSE for my daily driver, I decided to just stick with Ubuntu. To fit my preference for some light ricing and desktop configuration, I opted to start with Ubuntu Server and build up a system with only the apps I wanted.
Even taken on its own merits, Ubuntu is a good option for a daily driver no matter the user's level of experience. This is for several reasons.
It Just Works™
Nearly every version of Linux has issues with drivers at some point. The specifics vary depending on your hardware, but I've found that wifi and graphic cards on laptops are the main culprits.
My laptop happens to have hybrid graphics between an AMD Ryzen 5600 and an Nvidia RTX 3050 mobile. This has historically been a big problem on Linux, since configuring hybrid graphics setups involves a great deal of interplay between open-source and proprietary drivers.
On NixOS this issue wasn't so bad, and I was able to configure my setup using settings from the wiki. However, it did run less efficiently than on my previous (Debian) setup.
Meanwhile, on Ubuntu my drivers worked immediately on installation, with no need for additional configuration. While I did opt to switch power mode for performance reasons, this was trivial and the Nvidia app needed to do it was readily available as part of the package manager.
Ubuntu (and its derivatives, especially PopOS) is one of the few distributions I've seen which consistently has hardware work out of the box. While this might be offensive to Arch users, I tend to feel that most Linux users want to be able to customise their experience more than the details of how their hardware and system daemons are set up. I appreciate that Ubuntu handles the details of how to get my system running so I can focus on actually using it.
Widespread Support
Ubuntu is widely used by enthusiasts and small businesses. While evidence suggests it's been pushed out by Arch in the desktop space, for years it was the most dominant distro, and it's still much more widely used than Arch in server setups.
With widespread usage comes widespread support. Most serious projects target Ubuntu as one of their Linux targets, and many of them ship PPAs (community repositories) for Ubuntu. In addition, a lot of projects ship .deb
packages, which are compatible with every Debian-based distro, including Ubuntu.
NixOS has more limited official support. While it boasts the largest collection of packages, most of these are community-contributed and therefore vary in quality. Most Nix packages which I used worked but many of them lacked the configuration options which you get in other distributions.
Where Nix packages did have good configuration support, it was arguably a better experience than dealing with Ubuntu packages, but this was a minority of cases.
Conclusion
NixOS has significant advantages over more conventional distributions -- in the professional server and workstation space. However, for daily driving and desktop usage, there are better alternatives for most users.
If you're already a hardcore Linux nerd and don't mind spending a ton of time configuring and optimising your system, then NixOS might be for you. However, even for software engineers, NixOS can introduce problems that don't exist on conventional distributions. It can also exhibit unexpected behaviours like rebuilding from source on a configuration change.
While I generally disagree with the cliche that "Linux is free if you don't value your time", in desktop NixOS it feels that way. For people who see Linux as a blank canvas for DIY, this might be attractive. However, I prefer technology which improves my productivity, rather than hampering it.