NixOS modules: Difference between revisions

Dafitt (talk | contribs)
Added examples to Declarations
Blokyk (talk | contribs)
Add a "Disabling modules" section in advanced usages, partially migrated from the unofficial wiki
 
(6 intermediate revisions by one other user not shown)
Line 26: Line 26:
     # using the "option" above.  
     # using the "option" above.  
     # Options for modules imported in "imports" can be set here.
     # Options for modules imported in "imports" can be set here.
  };
  meta = {
    # Meta-attributes to provide extra information like documentation or maintainers.
   };
   };
}
}
Line 170: Line 174:
Imports are paths to other NixOS modules that should be included in the evaluation of the system configuration. A default set of modules is defined in {{Nixpkgs Link|nixos/modules/module-list.nix}}. These don't need to be added in the import list.  
Imports are paths to other NixOS modules that should be included in the evaluation of the system configuration. A default set of modules is defined in {{Nixpkgs Link|nixos/modules/module-list.nix}}. These don't need to be added in the import list.  


=== Declarations ===
=== Option Declarations ===


Declarations specify a module's external interfaces.
Declarations specify a module's external interfaces.
Line 176: Line 180:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
options = {
options = {
   optionName = mkOption {
   optionName = lib.options.mkOption {
     # ...
     # ...
   };
   };
Line 182: Line 186:
</syntaxhighlight>
</syntaxhighlight>


They are created with {{ic|mkOption}}, a function accepting a set with following attributes:<ref>{{Nixpkgs Link|lib/options.nix#L66-L88}}</ref><ref>{{manual:nixos|sec=#sec-option-declarations|chapter=42.1. Option Declarations}}</ref>
They are created with {{ic|mkOption}}, a function in <code>lib</code>.<ref>{{Nixpkgs Link|lib/options.nix#L66-L88}}</ref><ref>{{manual:nixos|sec=#sec-option-declarations|chapter=42.1. Option Declarations}}</ref>
 
<dl>
<dt><code>type</code></dt>
<dd><p>
      The type of the option. It may
      be omitted, but that’s not advisable since it may lead to errors that
      are hard to diagnose.
</p></dd>
<dt><code>default</code></dt>
<dd><p>
      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.
</p></dd>
<dt><code class="varname">example</code></dt>
<dd><p>
      An example value that will be shown in the NixOS manual.
</p></dd>
<dt><code>description</code></dt>
<dd><p>
      A textual description of the option, in DocBook format, that will be
      included in the NixOS manual.
</p></dd>
</dl>


==== Examples ====
==== Examples ====
[[File:NixOS Search - Options.png|alt=A search query `programs.bat.` on the official NixOS Search - Options.|thumb|268x268px|For more examples you can browse [https://github.com/NixOS/nixpkgs NixOS/nixpkgs]: Search a similar option on [https://search.nixos.org/options NixOS Search - Options] and click on the link beside "Declared in".]]
[[File:NixOS Search - Options.png|alt=A search query `programs.bat.` on the official NixOS Search - Options.|thumb|270x270px|For even more examples you can browse [https://github.com/NixOS/nixpkgs NixOS/nixpkgs]: Search a similar option on [https://search.nixos.org/options NixOS Search - Options] and click on the link beside "Declared in" and studding the option declarations.]]
Some useful option examples.<syntaxhighlight lang="nixos">
Some useful option examples:<syntaxhighlight lang="nixos">
{ lib, pkgs, ... }: {
{ lib, pkgs, ... }: {
   options.examples = {
   options.examples = {
Line 219: Line 198:
     package = lib.options.mkPackageOption pkgs "bash" { };
     package = lib.options.mkPackageOption pkgs "bash" { };
     # type = lib.types.package;
     # type = lib.types.package;
    numberOfTheDay = lib.options.mkOption {
      type = lib.types.ints.between 50 100;
      default = 61;
    };


     groceries = lib.options.mkOption {
     groceries = lib.options.mkOption {
Line 232: Line 216:


     settings = lib.options.mkOption {
     settings = lib.options.mkOption {
       type = lib.types.json;
       type = lib.types.toml;
       default = {};
       default = {};
       description = ''
       description = ''
         Showcase the possible option for settings of a configuration file.
         Showcase the possible option for settings of a configuration
        file.
         Always document, where you can find possible options e.g.:  
         Always document, where you can find possible options e.g.:  
           Refer <https://example.com/> for possible options.
           Refer <https://example.com/> for possible options.
Line 277: Line 262:
         "unit1" = { unit = "m" };
         "unit1" = { unit = "m" };
         "unit2".unit = "cm";
         "unit2".unit = "cm";
        "unit3" = {}; # kg
       };
       };
     };
     };
Line 290: Line 276:
To see how modules are setup and reuse other modules in practice put <code>hello.nix</code> in the same folder as your <code>configuration.nix</code>:
To see how modules are setup and reuse other modules in practice put <code>hello.nix</code> in the same folder as your <code>configuration.nix</code>:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">{ lib, pkgs, config, ... }:
{ lib, pkgs, config, ... }:
with lib;                       
with lib;                       
let
let
Line 299: Line 284:
   cfg = config.services.hello;
   cfg = config.services.hello;
in {
in {
  meta.doc = "Says hello every time you login.";
   # Declare what settings a user of this "hello.nix" module CAN SET.
   # Declare what settings a user of this "hello.nix" module CAN SET.
   options.services.hello = {
   options.services.hello = {
Line 317: Line 304:
     };
     };
   };
   };
}
}</syntaxhighlight>
</syntaxhighlight>


The other <code>configuration.nix</code> module can then import this <code>hello.nix</code> module  
The other <code>configuration.nix</code> module can then import this <code>hello.nix</code> module  
Line 388: Line 374:
* [https://gitlab.com/simple-nixos-mailserver/nixos-mailserver nixos-mailserver] - full-featured mail server module
* [https://gitlab.com/simple-nixos-mailserver/nixos-mailserver nixos-mailserver] - full-featured mail server module
* [https://github.com/xtruder/nix-profiles X-Truder Nix-profiles] - modules for Nix to quickly configure your system based on application profiles.
* [https://github.com/xtruder/nix-profiles X-Truder Nix-profiles] - modules for Nix to quickly configure your system based on application profiles.
=== Disabling modules ===
In some cases, you may wish to override or disable modules previously imported, for example by NixOS. This can be achieved using the top-level attribute <code>disabledModules</code><ref>[https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/development/replace-modules.section.md "Replace Modules" section, NixOS manual]</ref>. It prevents that module, as well as any module it imports itself, from being imported into the current config scope. This means that neither the options it declares nor the configuration it might set are actually imported. This can be particularly useful to override or debug the implementation of a certain module, for example to use a module from an unstable NixOS channel while using the stable version of every other module in the system.
To disable a given module, you must refer to it based on either:
* the full, absolute path of the module: <code>/mnt/dev/foo/my-modules/services/thingy.nix</code><syntaxhighlight lang="nix">
{ ... }: {
  imports = [ <jade-nur/modules> ];
  disabledModules = [
    # make sure that the GL module is never imported
    "/home/xia/custom-modules/gl.nix"
    # prevent the tilix module from 'jade-nur' being imported
    # note that this doesn't disable the rest of 'jade-nur/modules'
    <jade-nur/modules/programs/tilix.nix>
  ];
}
</syntaxhighlight>
* the path relative to the value of <code>modulesPath</code>: <code>"programs/hello.nix"</code><syntaxhighlight lang="nix">
{ ... }: {
  disabledModules = [
    # prevent NixOS's immich module from being imported
    "services/web-apps/immich.nix"
  ];
  imports = [
    # ...and then import a replacement of it from somewhere else
    <hotnix/services/immich>
  ];
}
</syntaxhighlight>
* an attribute set containing a <code>key</code> attribute, which should be a unique identity declared by the module you're trying to disable: <code>{ key = "my-super-unique-module"; }</code>. This is most useful for modules you have control over, as modules from NixOS and home-manager do not generally have specific keys.<syntaxhighlight lang="nix">
# in file foo.nix
{ ... }: {
  disabledModules = [
    # disable the module with the exact
    # key "staple-battery-horse", as well
    # as any module it imports itself
    { key = "staple-battery-horse"; }
  ];
  ...
}
# in file horse.nix, which could be imported
# from somewhere else in the config
{ ... }: {
  # this key should be globally unique, it is
  # the unique ID by which this module is tracked
  # by the module system, and thus how it can
  # be precisely disabled
  key = "stable-battery-horse";
  imports = [ ./impl.nix ];
  options = { ... };
}
</syntaxhighlight>
Note that keys and paths (whether absolute or relative) must be exact. For example, <code>disabledModules = [ "services/web-apps" ]</code> won't have any effect, because the files inside that folder are imported individually; however, <code>disabledModules = [ "services/web-apps/akkoma.nix" "services/web-apps/immich.nix" ... ];</code> will disable every module specified.
More examples are available in the [https://nixos.org/manual/nixos/unstable/#sec-replace-modules "Replace modules" section of the NixOS manual] .


== Under the hood  ==
== Under the hood  ==