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.
Command | Description |
---|---|
nixos-rebulid switch | Rebuilds the system from the /etc/nixos/configuration.nix file and switches to it |
nix-shell -p FOO | Enters 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 -d | Removes all old configuration generations |
nixos-rebuild boot | Repopulates the boot entries with the available generations (should be run after nix-collect-garbage ). |
nix-channel --update | Updates 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:
- Boot from the minimal ISO, which should drop you into a command line interface
- Partition the drive (I personally like to use
cfdisk
) - Format the partitions (
mkfs.fat
for boot partition,mkfs.ext4
for filesystem, etc) - Mount the partitions into
/mnt
- If using the unstable channel, use the commands above to switch to it
- Run
nixos-generate-config --root /mnt
to auto-generate the/mnt/etc/nixos
files (we really only needhardware-configuration.nix
) - Replace
/mnt/etc/nixos/configuration.nix
with your ownconfiguration.nix
, as well as any other.nix
files you may require - Simply run
nixos-install
to apply the configured settings