2021-09-18 10:52:07 +00:00
# Option Declarations {#sec-option-declarations}
An option declaration specifies the name, type and description of a
NixOS configuration option. It is invalid to define an option that
hasn't been declared in any module. An option declaration generally
looks like this:
```nix
2024-04-21 15:54:59 +00:00
{
options = {
name = mkOption {
type = type specification;
default = default value;
example = example value;
description = "Description for use in the NixOS manual.";
};
2021-09-18 10:52:07 +00:00
};
2024-04-21 15:54:59 +00:00
}
2021-09-18 10:52:07 +00:00
```
The attribute names within the `name` attribute path must be camel
cased in general but should, as an exception, match the [ package
attribute name](https://nixos.org/nixpkgs/manual/#sec-package-naming)
when referencing a Nixpkgs package. For example, the option
`services.nix-serve.bindAddress` references the `nix-serve` Nixpkgs
package.
The function `mkOption` accepts the following arguments.
`type`
2022-03-30 09:31:56 +00:00
: The type of the option (see [](#sec-option-types)). This
argument is mandatory for nixpkgs modules. Setting this is highly
recommended for the sake of documentation and type checking. In case it is
not set, a fallback type with unspecified behavior is used.
2021-09-18 10:52:07 +00:00
`default`
: The default value used if no value is defined by any module. A
default is not required; but if a default is not given, then users
of the module will have to define the value of the option, otherwise
an error will be thrown.
2021-10-06 13:57:05 +00:00
`defaultText`
: A textual representation of the default value to be rendered verbatim in
the manual. Useful if the default value is a complex expression or depends
on other values or packages.
2022-09-11 15:47:08 +00:00
Use `lib.literalExpression` for a Nix expression, `lib.literalMD` for
a plain English description in [Nixpkgs-flavored Markdown](
https://nixos.org/nixpkgs/manual/#sec-contributing-markup) format.
2021-10-06 13:57:05 +00:00
2021-09-18 10:52:07 +00:00
`example`
: An example value that will be shown in the NixOS manual.
2022-09-11 15:47:08 +00:00
You can use `lib.literalExpression` and `lib.literalMD` in the same way
2021-10-06 13:57:05 +00:00
as in `defaultText` .
2021-09-18 10:52:07 +00:00
`description`
2024-04-21 15:54:59 +00:00
: A textual description of the option in [Nixpkgs-flavored Markdown](
https://nixos.org/nixpkgs/manual/#sec-contributing-markup) format that will be
included in the NixOS manual.
2021-09-18 10:52:07 +00:00
2022-01-25 03:21:06 +00:00
## Utility functions for common option patterns {#sec-option-declarations-util}
### `mkEnableOption` {#sec-option-declarations-util-mkEnableOption}
Creates an Option attribute set for a boolean value option i.e an
option to be toggled on or off.
This function takes a single string argument, the name of the thing to be toggled.
The option's description is "Whether to enable \<name\>.".
For example:
::: {#ex-options-declarations-util-mkEnableOption-magic .example}
2023-05-24 13:37:59 +00:00
### `mkEnableOption` usage
2022-01-25 03:21:06 +00:00
```nix
2024-04-21 15:54:59 +00:00
lib.mkEnableOption "magic"
2022-01-25 03:21:06 +00:00
# is like
lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
2024-04-21 15:54:59 +00:00
description = "Whether to enable magic.";
2022-01-25 03:21:06 +00:00
}
```
2023-02-16 17:41:37 +00:00
:::
2022-01-25 03:21:06 +00:00
2023-10-19 13:55:26 +00:00
### `mkPackageOption` {#sec-option-declarations-util-mkPackageOption}
2022-01-25 03:21:06 +00:00
Usage:
```nix
mkPackageOption pkgs "name" { default = [ "path" "in" "pkgs" ]; example = "literal example"; }
```
Creates an Option attribute set for an option that specifies the package a module should use for some purpose.
**Note**: You shouldn’ t necessarily make package options for all of your modules. You can always overwrite a specific package throughout nixpkgs by using [nixpkgs overlays ](https://nixos.org/manual/nixpkgs/stable/#chap-overlays ).
2023-03-04 12:14:45 +00:00
The package is specified in the third argument under `default` as a list of strings
representing its attribute path in nixpkgs (or another package set).
Because of this, you need to pass nixpkgs itself (or a subset) as the first argument.
2022-01-25 03:21:06 +00:00
2023-03-04 12:14:45 +00:00
The second argument may be either a string or a list of strings.
It provides the display name of the package in the description of the generated option
(using only the last element if the passed value is a list)
and serves as the fallback value for the `default` argument.
2022-01-25 03:21:06 +00:00
2023-03-04 12:14:45 +00:00
To include extra information in the description, pass `extraDescription` to
append arbitrary text to the generated description.
You can also pass an `example` value, either a literal string or an attribute path.
The default argument can be omitted if the provided name is
an attribute of pkgs (if name is a string) or a
valid attribute path in pkgs (if name is a list).
If you wish to explicitly provide no default, pass `null` as `default` .
2022-01-25 03:21:06 +00:00
2023-02-16 17:41:37 +00:00
[]{#ex-options-declarations-util-mkPackageOption}
2022-01-25 03:21:06 +00:00
Examples:
::: {#ex-options-declarations-util-mkPackageOption-hello .example}
2023-05-24 13:37:59 +00:00
### Simple `mkPackageOption` usage
2022-01-25 03:21:06 +00:00
```nix
2023-10-19 13:55:26 +00:00
lib.mkPackageOption pkgs "hello" { }
2022-01-25 03:21:06 +00:00
# is like
lib.mkOption {
type = lib.types.package;
default = pkgs.hello;
defaultText = lib.literalExpression "pkgs.hello";
2024-04-21 15:54:59 +00:00
description = "The hello package to use.";
2022-01-25 03:21:06 +00:00
}
```
2023-02-16 17:41:37 +00:00
:::
2022-01-25 03:21:06 +00:00
::: {#ex-options-declarations-util-mkPackageOption-ghc .example}
2023-05-24 13:37:59 +00:00
### `mkPackageOption` with explicit default and example
2022-01-25 03:21:06 +00:00
```nix
2023-10-19 13:55:26 +00:00
lib.mkPackageOption pkgs "GHC" {
2022-01-25 03:21:06 +00:00
default = [ "ghc" ];
2022-09-22 12:36:57 +00:00
example = "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
2022-01-25 03:21:06 +00:00
}
# is like
lib.mkOption {
type = lib.types.package;
default = pkgs.ghc;
defaultText = lib.literalExpression "pkgs.ghc";
2022-09-22 12:36:57 +00:00
example = lib.literalExpression "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
2024-04-21 15:54:59 +00:00
description = "The GHC package to use.";
2022-01-25 03:21:06 +00:00
}
```
2023-02-16 17:41:37 +00:00
:::
2022-01-25 03:21:06 +00:00
2023-03-04 12:14:45 +00:00
::: {#ex-options-declarations-util-mkPackageOption-extraDescription .example}
2023-05-24 13:37:59 +00:00
### `mkPackageOption` with additional description text
2023-03-04 12:14:45 +00:00
```nix
mkPackageOption pkgs [ "python39Packages" "pytorch" ] {
extraDescription = "This is an example and doesn't actually do anything.";
}
# is like
lib.mkOption {
type = lib.types.package;
default = pkgs.python39Packages.pytorch;
defaultText = lib.literalExpression "pkgs.python39Packages.pytorch";
description = "The pytorch package to use. This is an example and doesn't actually do anything.";
}
```
:::
2021-09-18 10:52:07 +00:00
## Extensible Option Types {#sec-option-declarations-eot}
2024-06-05 15:53:02 +00:00
Extensible option types is a feature that allows to extend certain types
2021-09-18 10:52:07 +00:00
declaration through multiple module files. This feature only work with a
restricted set of types, namely `enum` and `submodules` and any composed
forms of them.
Extensible option types can be used for `enum` options that affects
multiple modules, or as an alternative to related `enable` options.
As an example, we will take the case of display managers. There is a
central display manager module for generic display manager options and a
2022-12-28 21:21:41 +00:00
module file per display manager backend (sddm, gdm ...).
2021-09-18 10:52:07 +00:00
2022-03-05 16:20:37 +00:00
There are two approaches we could take with this module structure:
2021-09-18 10:52:07 +00:00
2022-03-05 16:20:37 +00:00
- Configuring the display managers independently by adding an enable
2021-09-18 10:52:07 +00:00
option to every display manager module backend. (NixOS)
2022-03-05 16:20:37 +00:00
- Configuring the display managers in the central module by adding
an option to select which display manager backend to use.
2021-09-18 10:52:07 +00:00
Both approaches have problems.
Making backends independent can quickly become hard to manage. For
2022-03-05 16:20:37 +00:00
display managers, there can only be one enabled at a time, but the
type system cannot enforce this restriction as there is no relation
between each backend's `enable` option. As a result, this restriction
has to be done explicitly by adding assertions in each display manager
backend module.
2021-09-18 10:52:07 +00:00
2022-03-05 16:20:37 +00:00
On the other hand, managing the display manager backends in the
central module will require changing the central module option every
time a new backend is added or removed.
2021-09-18 10:52:07 +00:00
By using extensible option types, it is possible to create a placeholder
option in the central module
([Example: Extensible type placeholder in the service module](#ex-option-declaration-eot-service)),
and to extend it in each backend module
([Example: Extending `services.xserver.displayManager.enable` in the `gdm` module](#ex-option-declaration-eot-backend-gdm),
[Example: Extending `services.xserver.displayManager.enable` in the `sddm` module ](#ex-option-declaration-eot-backend-sddm )).
As a result, `displayManager.enable` option values can be added without
changing the main service module file and the type system automatically
2022-03-05 16:20:37 +00:00
enforces that there can only be a single display manager enabled.
2021-09-18 10:52:07 +00:00
::: {#ex-option-declaration-eot-service .example}
2023-05-24 13:37:59 +00:00
### Extensible type placeholder in the service module
2021-09-18 10:52:07 +00:00
```nix
2024-04-21 15:54:59 +00:00
{
services.xserver.displayManager.enable = mkOption {
description = "Display manager to use";
type = with types; nullOr (enum [ ]);
};
}
2021-09-18 10:52:07 +00:00
```
:::
::: {#ex-option-declaration-eot-backend-gdm .example}
2023-05-24 13:37:59 +00:00
### Extending `services.xserver.displayManager.enable` in the `gdm` module
2021-09-18 10:52:07 +00:00
```nix
2024-04-21 15:54:59 +00:00
{
services.xserver.displayManager.enable = mkOption {
type = with types; nullOr (enum [ "gdm" ]);
};
}
2021-09-18 10:52:07 +00:00
```
:::
::: {#ex-option-declaration-eot-backend-sddm .example}
2023-05-24 13:37:59 +00:00
### Extending `services.xserver.displayManager.enable` in the `sddm` module
2021-09-18 10:52:07 +00:00
```nix
2024-04-21 15:54:59 +00:00
{
services.xserver.displayManager.enable = mkOption {
type = with types; nullOr (enum [ "sddm" ]);
};
}
2021-09-18 10:52:07 +00:00
```
:::
The placeholder declaration is a standard `mkOption` declaration, but it
is important that extensible option declarations only use the `type`
argument.
Extensible option types work with any of the composed variants of `enum`
such as `with types; nullOr (enum [ "foo" "bar" ])` or `with types;
listOf (enum [ "foo" "bar" ])`.