NixOS

NixOS is a Linux distribution that forgoes the typical ideas of package manager structure in favor of its own, the Nix package manager. Rather than running commands to download and install programs and files somewhere, Nix's entire configuration is done in one of a handful of files, stored in /etc/nixos. I mean the entire configuration. The list of packages to be installed, the various settings for those packages, and even settings for hardware configurations are stored there. When new packages or configuration changes are needed, the entire system is rebuilt, creating a new immutable system with the requested packages. These changes are atomic and can be rolled back if there are any issues with the latest "generation". Because of this differing paradigm, Nix doesn't obey the typical Linux filesystem structure, instead creating its own directory structure in / as needed, although some items are kept for compatibility reasons (like /bin/sh).

This methodology has its pros and cons. Since the entire system is specified in its configuration files, it is completely reproducible. To recreate that exact system on an other machine, those files need to be copied over and the system rebuilt. This means, for example, that a test desktop can be completely set up within a VM before installing on real hardware, with only things like drive mounting and other hardware differences needing changes. However, while some things are much simpler, others seem to be much harder, such as managing services with systemd or installing programs yourself. Due to the immutability of the file system, you cannot just copy executables into /usr/bin and expect them to work, you need to write your own .nix configuration.

What about .config files?

By default, NixOS only manages system level configuration. For user-level items, such as a vim config for example, you still need to manage the .vimrc yourself, and store it in the correct place. This is also true for things such as DE settings, browser configuration, etc. There is a project known as "Home Manager" that extends the Nix paradigm to also manage user-level files. There are some downsides to this though, such as needing to convert all config files to the .nix syntax. For things such as my Neovim setup, this would require a fairly significant conversion for little reward, since that file is easily managed. I have yet to use Home Manager, but I may yet in the future.

Unstable

While NixOS uses a versioning system by default, there is the option to enable a rolling release-ish "unstable" version. To do so, you need to switch your default channel over then rebuild:


            # nix-channel --add https://nixos.org/channels/nixos-unstable
            # nix-channel --add https://nixos.org/channels/nixpkgs-unstable
            # nix-channel --update
            # nixos-rebuild switch --upgrade
            

Commands

There are a number of vital commands needed to rebuild the system when adding/deleting packages, cleaning up, and just trying programs out.

CommandDescription
nixos-rebulid switchRebuilds the system from the /etc/nixos/configuration.nix file and switches to it
nix-shell -p FOOEnters into a Nix shell with program FOO in the $PATH. NOTE: This is not persistent, the program will not exist after the shell is exited
nix-collect-garbage -dRemoves all old configuration generations
nixos-rebuild bootRepopulates the boot entries with the available generations (should be run after nix-collect-garbage).
nix-channel --updateUpdates all the software on the system (requires a switch after)

Custom software

Nix packages can be searched for at https://search.nixos.org/packages, and while it is a pretty exhaustive list, not everything has been made available there. It is possible to define your own custom Nix package, either to install on just your system or to submit to the nixpkgs monorepo for everyone to use.

There are many guides to writing a .nix package configuration, so I won't re-illustrate them here (plus it's kinda confusing), but actually getting a local Nix package installed on your system is not immediately clear. The easiest way I found is to put your .nix package specification into /etc/nixos and then include it into your configuration.nix file like so:


            environment.systemPackages = with pkgs; [
              (callPackage ./foo.nix {};)
            ];
            

This will treat the specified foo.nix like any other package specification, and build the system including it. Note, this can also go into user.user.USERNAME.packages, instead of environment.systemPackages.

Installing from existing configuration

Part of the appeal of a NixOS system is being able to create an install from a pre-existing configuration.nix file. While a first time install is more easily done using a NixOS image which includes a GUI, applying that configuration to a new system should be done with the minimal ISO, so that the system can apply without running into possibly misconfigured options. To do so: