% Extended Types for NixOS Modules % サニエ エリック % 2016年9月29日 - Tokyo NixOS Meetup
- Modules are the way to configure NixOS declaratively
services.xserver.enable = true;
- NixOS is fully configured via the module system in
configuration.nix
- Every module manage a particular functionality
- Option declaration: option creation in the module file (
mkOption
) - Option definition: setting the option a value in
configuration.nix
options
: The options declared by the module that can be used inconfiguration.nix
config
: The module functionality, setup NixOS according to the option definitions
-
options
is an attribute set of module options -
The options are declared with the
mkOption
function -
Options have a type set with the
type
key of themkOption
argumentservice.foo.port = mkOption { description = "The port that foo is listening"; type = types.int; default = 80; };
-
Options are defined in
configuration.nix
service.foo.port = 8080;
- Types provide mainly 2 functionalities:
- Type-check of definitions
- A way to possibly merge multiple options definitions
- Types can be separated in 3 categories:
- simple types:
int
,str
, ... - value types:
enum
enum [ 2 3 4 ]
,enum [ "left" "right" ]
- composed types:
listOf
,nullOr
, ...listOf int
,nullOr (enum [ "left" "right" ])
- simple types:
- EOT is a value types only feature (
enum
) - EOT provides declaration merging for value types
- EOT is a way to "extend"
enum
values through multiple modules
- A main type declaration
- Extended declarations in other module files
- Rules:
- The main declaration is a normal one
- Extended declarations must only define the
type
(nodescription
,check
, ...)
-
A service
foo
support multiple backends,bar
andbaz
-
foo
,bar
andbaz
are managed in different module files -
foo
backend type declaration:services.foo.backend = mkOption { description = "used backend"; type = types.enum [ "bar" "baz" ]; };
-
And in the
bar
backend module:config = mkIf (config.services.foo.backend == "bar") { ... };
-
Potential problems:
- if a backend is removed, or a new backend added
foo
type declaration must be updated - if
foo
and the backend maintainers are different and there are a lot of backends
- if a backend is removed, or a new backend added
-
EOT permits to define a "placeholder"
enum
option: -
foo
backend type declaration:services.foo.backend = mkOption { description = "used backend"; type = types.enum [ ]; };
-
and to "extend" it in other module files
-
bar
backend type extension:services.foo.backend = mkOption { type = types.enum [ "bar" ]; };
-
baz
backend type extension:services.foo.backend = mkOption { type = types.enum [ "baz" ]; };
- Improved maintainership
- Work with composed enum types, e.g.
nullOr (enum [])
,listOf (enum [])
- More "modular" modules
- Could simplify code using related
enable
options (Window managers, Display managers, ...)
PR content #18380
- added code is relatively small (~100 lines with comments) and simple to understand
types.nix
- type
functor
- type
typeMerge
function defaultTypeMerge
function
- type
module.nix
- type merge functionality in the
mergeOptionsDecls
- type merge functionality in the
- some little cleanups
- grouping related
enable
options into extendedenums
with backward compatibility (Input methods, Display managers, Window managers, ...) mkChangedOptionModule
andmkMergedOptionModule
#18922