Nixos generic image
Nixos

NixOS is a Linux distribution that is built around the Nix package manager. More information is in my previous post(s). This post is about the way I made my Nixos configuration modular and useable on different systems. It mixes a laptop with an erase-your-darlings setup with a more normal Nixos laptop configuration and a server setup. All this while reusing as much of the configuration(s) as possible.

Modularisation Link to heading

The general idea is simple. A Nixos configuration file can include other configuration files, this is done as follows:

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./t14s-hardware-configuration.nix
      ./parts/generic-boot-systemd.nix
      ./parts/generic-desktop.nix
      ./parts/generic.nix
      ./parts/virtualisation.nix
      ./parts/printing.nix

      ./parts/users.nix

      ./parts/apps-default.nix
      ./parts/apps-extra-cli.nix
      ./parts/apps-extra-desktop.nix
      ./parts/apps-extra-music.nix

      ./parts/fonts.nix
    ];

The listing above already shows how I like to setup my Nixos configuration. So what I do is isolate related items and combine them into a single reusable configuration. For example, the printing configuration is straightforward and looks as follows:

{ config, pkgs, ... }:

{
  services.printing = {
    enable = true;
    startWhenNeeded = true;
    drivers = [
      pkgs.splix
      pkgs.samsung-unified-linux-driver
    ];
    extraConf = "DefaultAuthType None";
  };
}

Each system which includes this configuration will be able to interface with my Samsung laser printer.

A more interesting configuration is my users.nix (which has -obviously- been edited for this post):

{ config, pkgs, ... }:

{
  # Define user accounts. Don't forget to set a hashed-password with ‘mkpasswd’.
  users.users.patrick = {
    isNormalUser = true;
    extraGroups = [ "fprint" "wheel" "networkmanager" "docker" "libvirtd" "dialout" ];
    shell = pkgs.zsh;
  };

  # Enable zshell
  programs.zsh.enable = true;

  # Keyring via PAM
  security.pam.services.patrick.enableGnomeKeyring = true;
}

Where the printing configuration basically sets up a single configuration item with the relevant options (services.printing), this users configuration sets up multiple different configuration items with their relevant options (users.users.patrick, programs.zsh, and security.pam).

I also use a schema to help me identify configuration items by filename. The following listing shows the naming scheme I use:

.
├── parts
│   ├── apps-default.nix
│   ├── apps-extra-cli.nix
│   ├── apps-extra-desktop.nix
│   ├── desktop-gnome.nix
│   ├── desktop-sway.nix
│   ├── fonts.nix
│   ├── generic-boot-systemd.nix
│   ├── generic-desktop.nix
│   ├── generic-server.nix
│   ├── printing.nix
│   ├── server-adguard.nix
│   ├── server-smart.nix
│   ├── server-tailscale.nix
│   ├── users.nix
│   ├── users-patrick.nix
│   ├── users-user2.nix
├── laptop-configuration.nix
├── laptop-hardware-configuration.nix
├── server-configuration.nix
└── server-hardware-configuration.nix

The top-level configuration files combinations (laptop- and server- configurations) will include the relevant configurations from the parts folder.

Applying this configuration Link to heading

These file are all stored in a git repository. The git repository is then cloned on each of mt Nixos systems.

A default Nixos system setup checks the /etc/nixos folder for the file configuration.nix. Since each system will have a separate setup (at least requiring a separate hardware-configuration file) we need to create the configuration.nix. However, that file is already create, but it has a different name. This we solve by simply symlinking the correct file:

$ cp -r ./* /etc/nixos/
$ ln -s /etc/nixos/desktop-configuration.nix /etc/nixos/configuration.nix

This creates the /etc/nixos/configuration.nix and prepares the system for standard Nixos commands for building and switching configurations.

Updating a configuration Link to heading

My Nixos configurations are shared between all my systems. Updating a configuration is simply editing them in the repo, pushing the changes to the remote git repository, and (again) copying the files to the /etc/nixos/ folder (see previous section).

That is all. It is super simple and easy to setup. However, it is powerfull, especially when combined with home-manager (which is a topic for a separate post).