[Nix-dev] NixOS: New scheme

Nicolas Pierron nicolas.b.pierron at gmail.com
Sun Nov 16 21:33:37 CET 2008

Hi list,

This mail is a draft about the description of the new writing style.
This mail is organized in many points to make my point clear and to
explain how to write your own nix expression to easily extend your
computer configuration without hacking NixOS.

1/ Introduction

1.1/ Why a new scheme ?

In the current version of NixOS, we have a lot of list that does not
have a corresponding option.  Therefore you have to put your hand and
hack NixOS by copying existing code.  Unfortunately, most of the time,
we don't understand what we are doing by copying and we often
duplicate features.

1.2/ New scheme goal

the new scheme aim at separating everything by module.  Each module is
composed by an interface and an implementation contained in the same
file.  A module have options that are defined by other modules that
are using it.  The job of one module is to process his own options and
convert them to low-level options defined by other modules.

At the end, the system configuration will only call your computer
configuration which will be translated to low-level options.  (The
evaluation is in the opposite order, Eelco bless laziness)

2/ Scheme

2.1/ Configuration file / Module

To support you reading, you can have a look at

A configuration file is the same as a module.  It starts with the
following syntax which declares everything you may need.

{pkgs, config, ...}:

- pkgs: Attribute set that contains every package (e.g.: pkgs.cron,
pkgs.keen4, ...)
- config: Attribute set that contains your computer configuration. (see ??)

The interface is defined in an option attribute set which follow the
usual hierarchy.  It use mkOption to declare every options.

The implementation need all other module used to implement it and the
options defined by this module with the attribute named "require"

  require = [
    # options needed for the implementation
    (import ../upstart-jobs/default.nix)

    # options defined by this module

At the end of the file, attributes are set like if this was your own
computer configuration file.

2.2/ Options

Options can have the following list of attribute:

- default: Default value
- example: Give an hint on the syntax accepted for this option.
- description: Give context information about the option and its role
in the configuration of the computer.
- merge: Function which have two arguments (the name of the attribute,
a list of value).  This function is called only if the option has been
defined by the user or by another module.  It convert the list of
values into a value which has the same type as the default value.
This function can also be used the check the correctness of the input.
- apply: Function which converts the option in something usable.
(e.g.: separate a list of path by semicolon)

  nssModules = pkgs.lib.mkOption {
    default = [];
    example = [ pkgs.nssmdns ];
    description = " .. skipped .. ";
    merge = pkgs.lib.mergeListOption;
    apply = pkgs.lib.makeLibraryPath;

2.3/ Config argument

The argument is quite unusual but allowed by Laziness of Nix.  This
argument corresponds to the configuration of your computer.  It is
computed by following the dependencies between the options.

You can see examples in
https://svn.nixos.org/repos/nix/nixos/trunk/upstart-jobs/cron.nix and
where the options are defined in function of the value of the enable
option of the same module.

  environment = {
    extraPackages = ifEnable [ pcmciaUtils ];

Infinite loop can easily be created if one module depends directly or
indirectly on itself.  Currently we just hope that such patterns would
not be required to compute a computer configuration.

3/ Current work

3.1/ Moving NixOS the new scheme

I have created/converted some easy jobs to give us some bases:
- https://svn.nixos.org/repos/nix/nixos/trunk/upstart-jobs/pcmcia.nix
- https://svn.nixos.org/repos/nix/nixos/trunk/upstart-jobs/cron.nix
- https://svn.nixos.org/repos/nix/nixos/trunk/upstart-jobs/cron/locate.nix

I have succeed to make convert upstart-jobs/default.nix to the new
scheme, but I cannot commit it currently because this could cause some
trouble as you may not synchronized NixPkgs with NixOS at the same
time. (should I commit it ?)

3.2/ Hardware configuration

As every extension doesn't need to hack NixOS to be introduced, we are
now able to create device specific configuration.
Some have already be done with my own devices and other that have been
extrated from NixOS:

- https://svn.nixos.org/repos/nix/configurations/trunk/hardware/network/
- https://svn.nixos.org/repos/nix/configurations/trunk/computer/compaq/presario/2144EA/

Therefore, if you are using a specific device which now generate a
message like "networking.enableIntel4965AGNFirmware: Oboslete
option.", then you should add the following line in your main
configuration file:

  require = [
    (import configurations/hardware/network/Intel4965AGN.nix)

4/ Conclusion

- modular
- user friendly (same as his main configuration file)

If you have any suggestion, idea, complains on this work, feel free to
patch this mail ;)

Nicolas Pierron
- If you are doing something twice then you should try to do it once.

More information about the nix-dev mailing list