My experience when switching to NixOS - Part 3

In the last part of the series I descripted what I did to install KDE on the machine and promised to explain the configuration setup in this article.

The KDE was removed since, as I read some comments from people raging against Kontact/KMail/Akonadi and that it is bloat which does not work. So, I’m back at i3 and the “old” setup. Anyways, the configuration setup did not change, and I will explain it in this part of the series.

Kontact or no Kontact

So, Akonadi, KMail, Kontact and the whole stuff does not work. I’ve heard that from several people at reddit and in several IRC channels. So I’m back at my old setup, including

  • offlineimap / msmtp for mailing services
  • mutt as mailreader (was: Kmail)
  • remind as calendar (was: KOrganizer)
  • wyrd as calendar interface (was: KOrganizer)
  • taskwarrior as task tool (was: KOrganizer)
  • abook as address book (was: KAdressbook)

The point is, that I must get this tools to get working with eachother properly to have something like Kontact. And I will do so.

But, of course, this is another problem and I will explain it in another blog post, maybe.

The configuration setup

That’s the part you’re interested in most, I guess. So here we go. I’ve already described the problem, I have several machines, which have some parts of configuration which is same on every machine, but some parts differ.

My approach is simple. I have several subsets of configuration I can include into eachother to build a complete configuration. My folder structure looks like this:

~/config/
    |
    +- nixos/
        |
        +- fs/
        +- nixpkgs/
        +- pkgs/
        +- services/
        +- users/

in ./nixpkgs/ I simply symlinked the ~/.nixpkgs/config.nix for version controlling purposes (~/config is a git repository on my machines).

So, I have several sets of configuration sorted by kind of configuration.

fs

The ./fs/ subdirectory contains file system configurations for each machine. Of course, these parts cannot be re-used by other machines most of the time, but I keep them in a special subdirectory to keep my setup clean and modular.

A file ./fs/some.nix looks like this:

{ ... }:
{
    fileSystems."/home" = {
        device = "/dev/sda2";
        fsType = "ext4";
        options = "nosuid,nodev,relatime";
    };
}

for example.

pkgs

In the ./pkgs/ subdirectory, there are package sets defined. Namingly:

./pkgs/
    |
    +- basePackages.nix
    +- desktopPackages.nix
    +- devPackages.nix

by now. Each of these files look like so:

pkgs: [
    pkgs.mosh
    pkgs.tmux
    ...
]

for example.

services

A file in ./services/ defines one service. I can include a service file for simply “installing” the services.

My ./service/ file for redshift looks like this, for example:

{
    services.redshift = {
        enable = true;
        latitude = "48.059402";
        longitude = "8.464087";
        temperature = {
            day = 5500;
            night = 3700;
        };
    };
}

Simple stuff.

users

And last, but not least: ./users/. I don’t think I have to explain this one, it looks like the service or file system definitions.

The machine configuration

What’s more important and interesting, is the actual machine configuration. The machine configuration is a single file which lives in my ~/config/nixos/ folder and is named like the host.

So, nox.nix, which is the configuration file for my testing machine, looks literally like this:

{ config, pkgs, ... }:

let
  configDir = /home/m/config/nixos;
in

{
  imports = [
    # Base configuration
    "${configDir}/base-configuration.nix"

    # Users
    "${configDir}/users/m.nix"

    # Services
    "${configDir}/services/synergyClient.nix"
    "${configDir}/services/x.i3.nix"
    "${configDir}/services/redshift.nix"
    "${configDir}/services/networkmanager.nix"
  ];

  # Define on which hard drive you want to install Grub.
  boot.loader.grub.device = "/dev/sda";

  networking.hostName = "nox";

  environment.systemPackages = let
    basePkgs    = import "${configDir}/pkgs/basePackages.nix" pkgs;
    devPkgs     = import "${configDir}/pkgs/devPackages.nix" pkgs;
    desktopPkgs = import "${configDir}/pkgs/desktopPackages.nix" pkgs;
  in
    basePkgs ++ devPkgs ++ desktopPkgs;

}

That’s the whole deal. You may notice, that there is a base-configuration.nix, I include in this file. This is a very generic default configuration for each machine. It simply defines the following stuff:

  • use grub2, but not where to install it
  • system language
  • default shell (bash for me)
  • timezone
  • enable “sudo”

So this is really just basic stuff each machine has to be configured to.

After linking the /etc/nixos/configuration.nix to the appropriate file in the configuration directory, nixos can be rebuild and everything just works ™.

Feel free to copy the described setup and adjust so it fits your needs! Feel also free to ask me questions about it.


In the next article of this series, I will explain my vim setup including the plugin setup. Be prepared, it will be awesome to manage all you vim plugins with the Nix package manager!

Stay tuned!