diff --git a/nixos/doc/manual/configuration/config-syntax.xml b/nixos/doc/manual/configuration/config-syntax.xml index 518d8eb627f8..430ecb4d7918 100644 --- a/nixos/doc/manual/configuration/config-syntax.xml +++ b/nixos/doc/manual/configuration/config-syntax.xml @@ -20,6 +20,5 @@ xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix </para> <xi:include href="../from_md/configuration/config-file.section.xml" /> <xi:include href="../from_md/configuration/abstractions.section.xml" /> - <xi:include href="modularity.xml" /> - <xi:include href="summary.xml" /> + <xi:include href="../from_md/configuration/modularity.section.xml" /> </chapter> diff --git a/nixos/doc/manual/configuration/modularity.section.md b/nixos/doc/manual/configuration/modularity.section.md new file mode 100644 index 000000000000..23854cb503e0 --- /dev/null +++ b/nixos/doc/manual/configuration/modularity.section.md @@ -0,0 +1,133 @@ +# Modularity {#sec-modularity} + +The NixOS configuration mechanism is modular. If your +`configuration.nix` becomes too big, you can split it into multiple +files. Likewise, if you have multiple NixOS configurations (e.g. for +different computers) with some commonality, you can move the common +configuration into a shared file. + +Modules have exactly the same syntax as `configuration.nix`. In fact, +`configuration.nix` is itself a module. You can use other modules by +including them from `configuration.nix`, e.g.: + +```nix +{ config, pkgs, ... }: + +{ imports = [ ./vpn.nix ./kde.nix ]; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.emacs ]; + ... +} +``` + +Here, we include two modules from the same directory, `vpn.nix` and +`kde.nix`. The latter might look like this: + +```nix +{ config, pkgs, ... }: + +{ services.xserver.enable = true; + services.xserver.displayManager.sddm.enable = true; + services.xserver.desktopManager.plasma5.enable = true; + environment.systemPackages = [ pkgs.vim ]; +} +``` + +Note that both `configuration.nix` and `kde.nix` define the option +[`environment.systemPackages`](options.html#opt-environment.systemPackages). When multiple modules define an +option, NixOS will try to *merge* the definitions. In the case of +[`environment.systemPackages`](options.html#opt-environment.systemPackages), that's easy: the lists of +packages can simply be concatenated. The value in `configuration.nix` is +merged last, so for list-type options, it will appear at the end of the +merged list. If you want it to appear first, you can use `mkBefore`: + +```nix +boot.kernelModules = mkBefore [ "kvm-intel" ]; +``` + +This causes the `kvm-intel` kernel module to be loaded before any other +kernel modules. + +For other types of options, a merge may not be possible. For instance, +if two modules define [`services.httpd.adminAddr`](options.html#opt-services.httpd.adminAddr), +`nixos-rebuild` will give an error: + +```plain +The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'. +``` + +When that happens, it's possible to force one definition take precedence +over the others: + +```nix +services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org"; +``` + +When using multiple modules, you may need to access configuration values +defined in other modules. This is what the `config` function argument is +for: it contains the complete, merged system configuration. That is, +`config` is the result of combining the configurations returned by every +module [^1] . For example, here is a module that adds some packages to +[`environment.systemPackages`](options.html#opt-environment.systemPackages) only if +[`services.xserver.enable`](options.html#opt-services.xserver.enable) is set to `true` somewhere else: + +```nix +{ config, pkgs, ... }: + +{ environment.systemPackages = + if config.services.xserver.enable then + [ pkgs.firefox + pkgs.thunderbird + ] + else + [ ]; +} +``` + +With multiple modules, it may not be obvious what the final value of a +configuration option is. The command `nixos-option` allows you to find +out: + +```ShellSession +$ nixos-option services.xserver.enable +true + +$ nixos-option boot.kernelModules +[ "tun" "ipv6" "loop" ... ] +``` + +Interactive exploration of the configuration is possible using `nix + repl`, a read-eval-print loop for Nix expressions. A typical use: + +```ShellSession +$ nix repl '<nixpkgs/nixos>' + +nix-repl> config.networking.hostName +"mandark" + +nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts +[ "example.org" "example.gov" ] +``` + +While abstracting your configuration, you may find it useful to generate +modules using code, instead of writing files. The example below would +have the same effect as importing a file which sets those options. + +```nix +{ config, pkgs, ... }: + +let netConfig = hostName: { + networking.hostName = hostName; + networking.useDHCP = false; +}; + +in + +{ imports = [ (netConfig "nixos.localdomain") ]; } +``` + +[^1]: If you're wondering how it's possible that the (indirect) *result* + of a function is passed as an *input* to that same function: that's + because Nix is a "lazy" language --- it only computes values when + they are needed. This works as long as no individual configuration + value depends on itself. diff --git a/nixos/doc/manual/configuration/modularity.xml b/nixos/doc/manual/configuration/modularity.xml deleted file mode 100644 index d6eee4e9d76e..000000000000 --- a/nixos/doc/manual/configuration/modularity.xml +++ /dev/null @@ -1,146 +0,0 @@ -<section xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id="sec-modularity"> - <title>Modularity</title> - - <para> - The NixOS configuration mechanism is modular. If your - <filename>configuration.nix</filename> becomes too big, you can split it into - multiple files. Likewise, if you have multiple NixOS configurations (e.g. for - different computers) with some commonality, you can move the common - configuration into a shared file. - </para> - - <para> - Modules have exactly the same syntax as - <filename>configuration.nix</filename>. In fact, - <filename>configuration.nix</filename> is itself a module. You can use other - modules by including them from <filename>configuration.nix</filename>, e.g.: -<programlisting> -{ config, pkgs, ... }: - -{ imports = [ ./vpn.nix ./kde.nix ]; - <xref linkend="opt-services.httpd.enable"/> = true; - <xref linkend="opt-environment.systemPackages"/> = [ pkgs.emacs ]; - <replaceable>...</replaceable> -} -</programlisting> - Here, we include two modules from the same directory, - <filename>vpn.nix</filename> and <filename>kde.nix</filename>. The latter - might look like this: -<programlisting> -{ config, pkgs, ... }: - -{ <xref linkend="opt-services.xserver.enable"/> = true; - <xref linkend="opt-services.xserver.displayManager.sddm.enable"/> = true; - <xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true; - <xref linkend="opt-environment.systemPackages"/> = [ pkgs.vim ]; -} -</programlisting> - Note that both <filename>configuration.nix</filename> and - <filename>kde.nix</filename> define the option - <xref linkend="opt-environment.systemPackages"/>. When multiple modules - define an option, NixOS will try to <emphasis>merge</emphasis> the - definitions. In the case of <xref linkend="opt-environment.systemPackages"/>, - that’s easy: the lists of packages can simply be concatenated. The value in - <filename>configuration.nix</filename> is merged last, so for list-type - options, it will appear at the end of the merged list. If you want it to - appear first, you can use <varname>mkBefore</varname>: -<programlisting> -<xref linkend="opt-boot.kernelModules"/> = mkBefore [ "kvm-intel" ]; -</programlisting> - This causes the <literal>kvm-intel</literal> kernel module to be loaded - before any other kernel modules. - </para> - - <para> - For other types of options, a merge may not be possible. For instance, if two - modules define <xref linkend="opt-services.httpd.adminAddr"/>, - <command>nixos-rebuild</command> will give an error: -<screen> -The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'. -</screen> - When that happens, it’s possible to force one definition take precedence - over the others: -<programlisting> -<xref linkend="opt-services.httpd.adminAddr"/> = pkgs.lib.mkForce "bob@example.org"; -</programlisting> - </para> - - <para> - When using multiple modules, you may need to access configuration values - defined in other modules. This is what the <varname>config</varname> function - argument is for: it contains the complete, merged system configuration. That - is, <varname>config</varname> is the result of combining the configurations - returned by every module - <footnote xml:id="footnote-nix-is-lazy"> - <para> - If you’re wondering how it’s possible that the (indirect) - <emphasis>result</emphasis> of a function is passed as an - <emphasis>input</emphasis> to that same function: that’s because Nix is a - “lazy” language — it only computes values when they are needed. This - works as long as no individual configuration value depends on itself. - </para> - </footnote> - . For example, here is a module that adds some packages to - <xref linkend="opt-environment.systemPackages"/> only if - <xref linkend="opt-services.xserver.enable"/> is set to - <literal>true</literal> somewhere else: -<programlisting> -{ config, pkgs, ... }: - -{ <xref linkend="opt-environment.systemPackages"/> = - if config.<xref linkend="opt-services.xserver.enable"/> then - [ pkgs.firefox - pkgs.thunderbird - ] - else - [ ]; -} -</programlisting> - </para> - - <para> - With multiple modules, it may not be obvious what the final value of a - configuration option is. The command <option>nixos-option</option> allows you - to find out: -<screen> -<prompt>$ </prompt>nixos-option <xref linkend="opt-services.xserver.enable"/> -true - -<prompt>$ </prompt>nixos-option <xref linkend="opt-boot.kernelModules"/> -[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ] -</screen> - Interactive exploration of the configuration is possible using <command>nix - repl</command>, a read-eval-print loop for Nix expressions. A typical use: -<screen> -<prompt>$ </prompt>nix repl '<nixpkgs/nixos>' - -<prompt>nix-repl> </prompt>config.<xref linkend="opt-networking.hostName"/> -"mandark" - -<prompt>nix-repl> </prompt>map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHosts"/> -[ "example.org" "example.gov" ] -</screen> - </para> - - <para> - While abstracting your configuration, you may find it useful to generate - modules using code, instead of writing files. The example below would have - the same effect as importing a file which sets those options. -<programlisting> -{ config, pkgs, ... }: - -let netConfig = hostName: { - networking.hostName = hostName; - networking.useDHCP = false; -}; - -in - -{ imports = [ (netConfig "nixos.localdomain") ]; } -</programlisting> - </para> -</section> diff --git a/nixos/doc/manual/from_md/configuration/modularity.section.xml b/nixos/doc/manual/from_md/configuration/modularity.section.xml new file mode 100644 index 000000000000..d5db37c13cfb --- /dev/null +++ b/nixos/doc/manual/from_md/configuration/modularity.section.xml @@ -0,0 +1,154 @@ +<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-modularity"> + <title>Modularity</title> + <para> + The NixOS configuration mechanism is modular. If your + <literal>configuration.nix</literal> becomes too big, you can split + it into multiple files. Likewise, if you have multiple NixOS + configurations (e.g. for different computers) with some commonality, + you can move the common configuration into a shared file. + </para> + <para> + Modules have exactly the same syntax as + <literal>configuration.nix</literal>. In fact, + <literal>configuration.nix</literal> is itself a module. You can use + other modules by including them from + <literal>configuration.nix</literal>, e.g.: + </para> + <programlisting language="bash"> +{ config, pkgs, ... }: + +{ imports = [ ./vpn.nix ./kde.nix ]; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.emacs ]; + ... +} +</programlisting> + <para> + Here, we include two modules from the same directory, + <literal>vpn.nix</literal> and <literal>kde.nix</literal>. The + latter might look like this: + </para> + <programlisting language="bash"> +{ config, pkgs, ... }: + +{ services.xserver.enable = true; + services.xserver.displayManager.sddm.enable = true; + services.xserver.desktopManager.plasma5.enable = true; + environment.systemPackages = [ pkgs.vim ]; +} +</programlisting> + <para> + Note that both <literal>configuration.nix</literal> and + <literal>kde.nix</literal> define the option + <link xlink:href="options.html#opt-environment.systemPackages"><literal>environment.systemPackages</literal></link>. + When multiple modules define an option, NixOS will try to + <emphasis>merge</emphasis> the definitions. In the case of + <link xlink:href="options.html#opt-environment.systemPackages"><literal>environment.systemPackages</literal></link>, + that’s easy: the lists of packages can simply be concatenated. The + value in <literal>configuration.nix</literal> is merged last, so for + list-type options, it will appear at the end of the merged list. If + you want it to appear first, you can use + <literal>mkBefore</literal>: + </para> + <programlisting language="bash"> +boot.kernelModules = mkBefore [ "kvm-intel" ]; +</programlisting> + <para> + This causes the <literal>kvm-intel</literal> kernel module to be + loaded before any other kernel modules. + </para> + <para> + For other types of options, a merge may not be possible. For + instance, if two modules define + <link xlink:href="options.html#opt-services.httpd.adminAddr"><literal>services.httpd.adminAddr</literal></link>, + <literal>nixos-rebuild</literal> will give an error: + </para> + <programlisting> +The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'. +</programlisting> + <para> + When that happens, it’s possible to force one definition take + precedence over the others: + </para> + <programlisting language="bash"> +services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org"; +</programlisting> + <para> + When using multiple modules, you may need to access configuration + values defined in other modules. This is what the + <literal>config</literal> function argument is for: it contains the + complete, merged system configuration. That is, + <literal>config</literal> is the result of combining the + configurations returned by every module <footnote> + <para> + If you’re wondering how it’s possible that the (indirect) + <emphasis>result</emphasis> of a function is passed as an + <emphasis>input</emphasis> to that same function: that’s because + Nix is a <quote>lazy</quote> language — it only computes values + when they are needed. This works as long as no individual + configuration value depends on itself. + </para> + </footnote> . For example, here is a module that adds some packages + to + <link xlink:href="options.html#opt-environment.systemPackages"><literal>environment.systemPackages</literal></link> + only if + <link xlink:href="options.html#opt-services.xserver.enable"><literal>services.xserver.enable</literal></link> + is set to <literal>true</literal> somewhere else: + </para> + <programlisting language="bash"> +{ config, pkgs, ... }: + +{ environment.systemPackages = + if config.services.xserver.enable then + [ pkgs.firefox + pkgs.thunderbird + ] + else + [ ]; +} +</programlisting> + <para> + With multiple modules, it may not be obvious what the final value of + a configuration option is. The command + <literal>nixos-option</literal> allows you to find out: + </para> + <programlisting> +$ nixos-option services.xserver.enable +true + +$ nixos-option boot.kernelModules +[ "tun" "ipv6" "loop" ... ] +</programlisting> + <para> + Interactive exploration of the configuration is possible using + <literal>nix repl</literal>, a read-eval-print loop for Nix + expressions. A typical use: + </para> + <programlisting> +$ nix repl '<nixpkgs/nixos>' + +nix-repl> config.networking.hostName +"mandark" + +nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts +[ "example.org" "example.gov" ] +</programlisting> + <para> + While abstracting your configuration, you may find it useful to + generate modules using code, instead of writing files. The example + below would have the same effect as importing a file which sets + those options. + </para> + <programlisting language="bash"> +{ config, pkgs, ... }: + +let netConfig = hostName: { + networking.hostName = hostName; + networking.useDHCP = false; +}; + +in + +{ imports = [ (netConfig "nixos.localdomain") ]; } +</programlisting> +</section>