Modules with Declarations

In this section, we'll look at an example of a module from <nixpkgs/nixos/modules> that declares some options to provide a session for the i3 window manager.

(Comments and formatting are my own)

# <nixpkgs/nixos/modules/services/x11/window-managers/i3.nix>

{ config, lib, pkgs, ... }: with lib; let
  # it's convention to define `cfg` as your own config
  cfg = config.services.xserver.windowManger.i3;
in {
  options = {
    services.xserver.windowManager.i3 = {
      # lib.mkEnableOption generates an option that accepts a bool and has the
      # description "Whether to enable {arg}"
      enable = mkEnableOption "i3 window manager";

      # lib.mkOption is more general and accepts a whole set of options.
      # in this case, a default value, a description, and a lib.types type
      configFile = mkOption {
        default = null;
        type = with types; nullOr path;
        description = ''
          Path to the i3 configuration file.
          If left at the default value, $HOME/.i3/config will be used.
        '';
      };

      extraSessionCommands = mkOption {
        default = "";
        type = types.lines;
        description = ''
          Shell commands executed just before i3 is started.
        '';
      }

      # sometimes packages have multiple variants you can use in place of the 
      # original.
      # in these cases, an option `package` is usually supplied to configure
      # what the module puts in your environment.
      package = mkOption {
        type = types.package;
        default = pkgs.i3;
        defaultText = "pkgs.i3";
        example = "pkgs.i3-gaps";
        description = ''
          i3 package to use.
        '';
      };

      extraPackages = mkOption {
        type = with types; listOf package;
        default = with pkgs; [ dmenu i3status i3lock ];
        example = literalExample ''
          with pkgs; [
            dmenu
            i3status
            i3lock
          ]
        '';
        description = ''
          Extra packages to be installed system wide.
        '';
      };
    };
  };

  # lib.mkIf only applies configuration if the predicate is true
  config = mkIf cfg.enable {
    environment.systemPackages = [ cfg.package ] ++ cfg.extraPackages;

    environment.etc."i3/config" = mkIf (cfg.configFile != null) {
      source = cfg.configFile;
    };

    services.xserver.windowManager.session = [
      {
        name = "i3";
        start = ''
          ${cfg.extraSessionCommands}

          # lib.optionalString returns "" if the predicate is false
          ${cfg.package}/bin/i3 ${optionalString (cfg.configFile != null)
            "-c /etc/i3/config"
          } &
          waitPID=$!
        '';
      };
    ];
  };

  imports = [
    # lib.mkRemovedOptionModule returns a path to a module with a single option
    # that throws an error message
    (mkRemovedOptionModule [ "services" "xserver" "windowManager" "i3-gaps" "enable" ]
      "Use services.xserver.windowManager.i3.enable and set services.xserver.windowManager.i3.package to pkgs.i3-gaps to use i3-gaps.")
  ];
}

As you can see, it's pretty simple. If you enable it, you get the i3 package and an X session that runs the provided binary. Like most modules, it makes heavy use of the library provided in <nixpkgs/lib>.