summary refs log tree commit diff
path: root/nixos/doc/manual/from_md/configuration/modularity.section.xml
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/doc/manual/from_md/configuration/modularity.section.xml')
-rw-r--r--nixos/doc/manual/from_md/configuration/modularity.section.xml152
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 [ &quot;kvm-intel&quot; ];
+</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 &quot;bob@example.org&quot;;
+</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
+[ &quot;tun&quot; &quot;ipv6&quot; &quot;loop&quot; ... ]
+</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 '&lt;nixpkgs/nixos&gt;'
+
+nix-repl&gt; config.networking.hostName
+&quot;mandark&quot;
+
+nix-repl&gt; map (x: x.hostName) config.services.httpd.virtualHosts
+[ &quot;example.org&quot; &quot;example.gov&quot; ]
+</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 &quot;nixos.localdomain&quot;) ]; }
+</programlisting>
+</section>