diff options
Diffstat (limited to 'nixos/doc/manual/from_md/configuration/modularity.section.xml')
-rw-r--r-- | nixos/doc/manual/from_md/configuration/modularity.section.xml | 152 |
1 files changed, 152 insertions, 0 deletions
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 00000000000..a7688090fcc --- /dev/null +++ b/nixos/doc/manual/from_md/configuration/modularity.section.xml @@ -0,0 +1,152 @@ +<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 + <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 + <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 + <xref linkend="opt-services.httpd.adminAddr" />, + <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 <xref linkend="opt-environment.systemPackages" /> only if + <xref linkend="opt-services.xserver.enable" /> 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> |