NixOS Configuration

Published: May 1, 2015, 9 p.m.

Updated: None

One of the attractive features of NixOS is the ability to declaratively configure all aspects of the system from one configuration file called configuration.nix or for manageability, with this file and input files -- imports in the nix expression terminology --) that are called from this file. Even nix expressions (package build scripts) that can initiate a custom package build, starting from downloading a source tarball to configuring the custom package, can be integrated into this single file configuration system. This guide will provide examples of a configuration I have used.

The configuration.nix file.

Besides being one of NixOS's powerful features, because of the OS's nonstandard directory heirarchy, it is necessary to configure nearly every aspect of the system by specifying attributes in the configuration.nix file. The exception to items that must be configured using the configuration.nix file are settings that can be configured from within the desktop environment, for example, using KDE's "System Settings" control panel, although not all settings that can be configured with this tool in standard Linux distributions can be used in NixOS.

The format of *.nix files.

This file needs at its top the statement { config, pkgs, ... }: with everything else in the file inclosed in braces. Text can be commented with #, where all characters that follow are ignored. Individual statements must end with a ;. The following is the main configuration file I used.


# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      ./desktop-applications.nix
      ./sysPkgs.nix
      ./sysPkgsinternet.nix
      ./nixpkgs.nix
      #./hosts.nix
      #./hardware.nix
    ];

  # Use the gummiboot efi boot loader.
  boot.loader.gummiboot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  boot.loader.gummiboot.timeout = 30;

  networking.hostName = "V570-NIXOS"; # Define your hostname.
  networking.wireless.enable = true;  # Enables wireless.
  #networking.networkmanager.enable = true;


  # Select internationalisation properties.
  i18n = {
    consoleFont = "lat9w-16";
    consoleKeyMap = "us";
    defaultLocale = "en_US.UTF-8";
  };

  time.timeZone = "America/New_York";

  # List packages installed in system profile. To search by name, run:
  # -env -qaP | grep wget
  # environment.systemPackages = with pkgs; [
  #   wget
  # ];

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  # services.openssh.enable = true;

  # Enable CUPS to print documents.
  # services.printing.enable = true;

  # Enable the X11 windowing system.
  #services.xserver.enable = true;
  #services.xserver.layout = "us";
  # services.xserver.xkbOptions = "eurosign:e";
  #services.xserver.synaptics.enable = true;

  services = {
    xserver = {
      enable = true;
      layout = "us";
      #defaultDepth = 24;
      #videoDriver = "intel";
      #exportConfiguration = true;
      #enableTCP = true;
      #autorun = true;
      #driSupport = false;
      synaptics = {
	enable = true;
	#dev = "/dev/input/event8";
      };
    };
  };

  # Enable the KDE Desktop Environment.
  services.xserver.displayManager.kdm.enable = true;
  services.xserver.desktopManager.kde4.enable = true;

  # Define a user account. Don't forget to set a password with ‘passwd’.
  # users.extraUsers.guest = {
  #   name = "guest";
  #   group = "users";
  #   uid = 1000;
  #   createHome = true;
  #   home = "/home/guest";
  #   shell = "/run/current-system/sw/bin/bash";
  # };

}

In the above code block which contains the configuration.nix file,

lines 8 - 17
specify secondary configuration files to be imported into the main configuration file
lines 19 - 22
specify the bootloader to be used
ines 29 - 34
specify locale settings
line 36
specifies the time zone
lines 38 - 39
a hint written by the installer
lines 40 - 42
also a hint from the installer providing the statement necessary for installing system-wide packages to be installed in the configuration
lines 52 - 56
enable xserver and specify its settings. this was written by the installer
lines 58 - 71
these lines are the same, with a few additional xserver attributes, as lines 52 - 56, with the exception that they are written in the more convenient nested form
lines 76 - 77
these statements are necessary to enable the KDE display manager and the KDE desktop
lines 79 - 87
creates a user and specifies the user account settings. I created a user after installation in a console, because the NIxOS Manual mentions problems that can occur after updates when creating an account directly in the configuration file

Secondary*.nix files.

To make the file manageble, attributes that can logically be grouped together can be placed in separate files with the extension .nix. For example, attributes that install KDE components, attributes that specify systemwide software installation, and attributes that specify hardware configuration, can be placed in their own files. These files are included in the main configuration file with the statement:


imports =
    [

    ];
    
    

The secondary files, like the main configuration file, must have { config, pkgs, ... }: as the first line and all other statements must be enclosed by braces as well. These files are listed inside the brackets of the imports statement as in:


imports = [ # Include the results of the hardware scan
	./hardware-configuration.nix
	./desktop-applications.nix
	./sysPkgs.nix
	./sysPkgsinternet.nix
	./nixpkgs.nix
	#./hosts.nix
];

Note that the file names of the secondary files include a relative path to the location of the configuration.nix file, which is created in /etc/nixos by the installer.

The secondary file that is imported into the main configuration file on line 2 of the above snippet is created by default during the NixOS installation and includes basic hardware configuration related to booting. The filesystems that should be mounted at boot are specified here by the installer based on what is mounted by the user during the installation. The swap partition is also activated here based on the user activated swap partition during installation. Kernel modules deemed appropriate by the installer are specified automatically by the installer here also. The hardware-configuration.nix file is shown below.


# Do not modify this file!  It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations.  Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, pkgs, ... }:

{
  imports =
    [ 
    ];

  boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];

  fileSystems."/" =
    { device = "/dev/sda14";
      fsType = "ext4";
    };

  fileSystems."/home" =
    { device = "/dev/sda15";
      fsType = "ext4";
    };

  fileSystems."/boot" =
    { device = "/dev/sda2";
      fsType = "vfat";
    };

  swapDevices =
    [ { device = "/dev/sda8"; }
    ];

  nix.maxJobs = 4;
}

Two of the other files imported into the main configuration file -- desktop-applications.nix and sysPkgsinternet.nix -- are files that include straightforward declarations of packages that should be included in the system configuration, i.e., those that should be installed on the system. nixpkgs.nix configures or modifies the referenced software in the file.sysPkgs.nix is similar to the desktop-applications.nix file in that it declaratively specifies software to be installed, but it also includes a declaratively installed package that is custom built by calling another file that is a nix expression (build script) to build the package. The structure of these files are discussed in sections below.

Attributes in *.nix files.

Attribute names are hierarchically organized through the use of qualifiers. In the attribute boot.loader.gummiboot.enable, boot is the top level qualifier, and loader and gummiboot are intermediate level qualifiers. This system allows attribute specifications to be nested as in the following:


services = {
	xserver = {
		enable = true;
		layout = "us";
		synaptics = {
	enable = true;
		};
	};
};

which is equivalent to writing


services.xserver.enable = true;
services.xserver.layout = "us";
services.xserver.synaptics.enable = true;

The entire list of available attributes and permissible values are listed in Appendix B of the .

Specifying packages to be installed system-wide in *.nix

Packages can be declaratively installed by including them in the list of sytem-wide packages with the statement


environment.systemPackages = with pkgs; [

  ];

The packages to be installed are listed inside the brackets of the above statement. desktop-applications.nix and sysPkgsinternet.nix, which are included or "imported" into configuration.nix install packages system-wide declaratively using the statement in the previous snippet. In desktop-applications.nix, which is listed in the following code block, the desired KDE packages are listed between the brackets.


{ config, pkgs, ... }:

{
# KDE packages

environment.systemPackages = with pkgs; [
	kde4.networkmanagement
	kde4.kdemultimedia
	kde4.kdegraphics
	kde4.kdeutils
	kde4.applications
	#pkgs.kde4.kdegames
	#pkgs.kde4.kdeedu
	kde4.kdebindings
	kde4.kdeaccessibility
	kde4.kde_baseapps
	kde4.kactivities
	kde4.kdeadmin
	kde4.kdeartwork
	kde4.kde_base_artwork
	kde4.kdenetwork
	kde4.kdepim
	kde4.kdepimlibs
	kde4.kdeplasma_addons
	kde4.kdesdk
	kde4.kdetoys
	kde4.kde_wallpapers
	kde4.kdewebdev
	kde4.oxygen_icons
	kde4.kdebase_workspace
	kde4.kdelibs
	kde4.kdevelop
	kde4.kdevplatform

	kde4.qtcurve
	kde4.ColorSchemes
	kde4.desktopthemes
	kde4.kscreensaver
	kde4.kwin_styles
	kde4.partitionManager
	kde4.qt4
	kde4.yakuake

	kde4.kgpg

	];
}

In sysPkgsinternet.nix, which is listed in the following code block,


{ config, pkgs, ... }:

{

environment.systemPackages = with pkgs; [
  chromiumWrapper
  firefoxWrapper
];
}

Note that if you don't include with pkgs; in

environment.systemPackages = with pkgs;,

you will have to prefix each of the package names with pkgs.

In nixpkgs.nix, listed below,


{ config, pkgs, ... }:

# Nixpkgs options (like repository options)

{
  nixpkgs.config.allowUnfree = true;
  nixpkgs.config.firefox.enableAdobeFlash = true; # for Firefox

  nixpkgs.config.chromium.enableAdobeFlash = true; # for Chromium
  nixpkgs.config.chromium.enablePepperFlash = true;
  nixpkgs.config.chromium.enablePepperPDF = true;
}

the packages browsers declared in sysPkgsinternet.nix are configured to use Adobe Flash Player, Pepper PDF, and Pepper Flash Player plugins, meaning that these plugins will be installed during the building of the configuration. Line 6 of this file is necessary to allow these and other non-free packages to be installed on the system.

Specifying a custom built package in *.nix

Anyone who commits to using NixOS past a cursory trial, will need to specify a package that is custom built, either because it is not available in the NixOS channels, a recent version is not available, or the user wants to customize the build. In my case, I needed a newer version of LyX in order to be able to open and modify LyX files created with a newer version of LyX on other Linux distributions. The method I used can serve as an example of one method of doing this.

The first step was to write a nix expression to build the package, using the expression that is viewable on packages.nixos.org which for the LyX package in the NixOS 14.04 channel was specifically at this page. After modification the nix expression looked like the following code block.


# Custom build of Lyx version 2.1.1 which is not available in the Nixpkgs 14.04
# channel as of 8/14/04.
# Modifying the expression in Nixpkgs of versiotn 2.0.7 to allow hunspell and
# enchant spell checkers.

with import  { #fetchurl stdenv texLive python
#pkgconfig libX11 qt4 enchant hunspell #mythes, boost
};

stdenv.mkDerivation rec {
  version = "2.1.1";
  name = "lyx-$ {version}";

  src = fetchurl {
    url = "ftp://ftp.lyx.org/pub/lyx/stable/2.1.x/${name}.tar.xz";
    sha256 = "1fir1dzzy7c92jf3a3psnd10c6widslk0852xk4svpl6phcg4nya";
  };

  configureFlags = [
    "--without-included-boost"
    /*  Boost is a huge dependency from which 1.4 MB of libs would be used.
        Using internal boost stuff only increases executable by around 0.2 MB. */
    "--without-included-mythes" # such a small library isn't worth a separate
    #package
  ];

  buildInputs = [
    pkgconfig qt4 python file bc texLive makeWrapper #libX11
    enchant hunspell mythes boost
  ];

  doCheck = true;

    postFixup = ''
    sed '1s:/usr/bin/python:${python}/bin/python:'

    wrapProgram "$out/bin/lyx" \
      --prefix PATH : '${python}/bin'
  '';

  meta = {
    description = "LyX 2.1.1 customized for local installation";
    homepage = "http://www.lyx.org";
    license = stdenv.lib.licenses.gpl2;
    maintainers = [ stdenv.lib.maintainers.vcunat ];
    platforms = stdenv.lib.platforms.linux;
  };
}

The elements of the original file that I changed were

lines 6 - 8
added with import < nixpkgs > and commented out everything in the brackets. This change puts all packages and nix tools into scope for building the package so if they are needed due to statements in the rest of the expression, they will be available, instead of just those that are in the braces of the original expression
line 11
changed the version to the version being currently built
line 15
changed the url of the source tarball to the one that will be downloaded when this nix configuration is built
line 16
updated the sha256 checksum to that of the new tarball
lines 27 - 30
added build dependencies enchant to provide a an additional spellchecker
line 42
updated the description

I saved this expression as the file my-lyx.nix in /etc/nixos.

The second and last step was to include this expression into the environment.systemPackages list. I included it in the secondary configuration file sysPkgs.nix which was itself imported into the main configuration file in line 12 of the configuration.nix. sysPkgs.nix is shown in the following code block.


{ config, pkgs, ... }:

{

environment.systemPackages = with pkgs; [
  texLive
  texLiveExtra
  texLivePGF
  texLiveLatexXColor
  texLiveContext
  texLiveBeamer
  texLiveModerncv
  texLiveModerntimeline
  #tetex
  #texLiveFull
  (import ./my-lyx.nix)
];

}

Conclusion

With the configuration files listed in this article in place in /etc/nixos, when the command nixos-rebuild switch is executed, the configuration declared in this set of files will be built. The configuration building process will configure the system as specified, install all packages, with all necessary dependencies, downloading sources, compiling, and building packages as necessary.