summaryrefslogtreecommitdiffstats
path: root/nixos/doc/manual/from_md/configuration/linux-kernel.chapter.xml
blob: 058a890d7a3e3e8cb3f3d64ea91dcb76a1734c3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-kernel-config">
  <title>Linux Kernel</title>
  <para>
    You can override the Linux kernel and associated packages using the
    option <literal>boot.kernelPackages</literal>. For instance, this
    selects the Linux 3.10 kernel:
  </para>
  <programlisting language="bash">
boot.kernelPackages = pkgs.linuxKernel.packages.linux_3_10;
</programlisting>
  <para>
    Note that this not only replaces the kernel, but also packages that
    are specific to the kernel version, such as the NVIDIA video
    drivers. This ensures that driver packages are consistent with the
    kernel.
  </para>
  <para>
    While <literal>pkgs.linuxKernel.packages</literal> contains all
    available kernel packages, you may want to use one of the
    unversioned <literal>pkgs.linuxPackages_*</literal> aliases such as
    <literal>pkgs.linuxPackages_latest</literal>, that are kept up to
    date with new versions.
  </para>
  <para>
    Please note that the current convention in NixOS is to only keep
    actively maintained kernel versions on both unstable and the
    currently supported stable release(s) of NixOS. This means that a
    non-longterm kernel will be removed after it’s abandoned by the
    kernel developers, even on stable NixOS versions. If you pin your
    kernel onto a non-longterm version, expect your evaluation to fail
    as soon as the version is out of maintenance.
  </para>
  <para>
    Longterm versions of kernels will be removed before the next stable
    NixOS that will exceed the maintenance period of the kernel version.
  </para>
  <para>
    The default Linux kernel configuration should be fine for most
    users. You can see the configuration of your current kernel with the
    following command:
  </para>
  <programlisting>
zcat /proc/config.gz
</programlisting>
  <para>
    If you want to change the kernel configuration, you can use the
    <literal>packageOverrides</literal> feature (see
    <xref linkend="sec-customising-packages" />). For instance, to
    enable support for the kernel debugger KGDB:
  </para>
  <programlisting language="bash">
nixpkgs.config.packageOverrides = pkgs: pkgs.lib.recursiveUpdate pkgs {
  linuxKernel.kernels.linux_5_10 = pkgs.linuxKernel.kernels.linux_5_10.override {
    extraConfig = ''
      KGDB y
    '';
  };
};
</programlisting>
  <para>
    <literal>extraConfig</literal> takes a list of Linux kernel
    configuration options, one per line. The name of the option should
    not include the prefix <literal>CONFIG_</literal>. The option value
    is typically <literal>y</literal>, <literal>n</literal> or
    <literal>m</literal> (to build something as a kernel module).
  </para>
  <para>
    Kernel modules for hardware devices are generally loaded
    automatically by <literal>udev</literal>. You can force a module to
    be loaded via <xref linkend="opt-boot.kernelModules" />, e.g.
  </para>
  <programlisting language="bash">
boot.kernelModules = [ &quot;fuse&quot; &quot;kvm-intel&quot; &quot;coretemp&quot; ];
</programlisting>
  <para>
    If the module is required early during the boot (e.g. to mount the
    root file system), you can use
    <xref linkend="opt-boot.initrd.kernelModules" />:
  </para>
  <programlisting language="bash">
boot.initrd.kernelModules = [ &quot;cifs&quot; ];
</programlisting>
  <para>
    This causes the specified modules and their dependencies to be added
    to the initial ramdisk.
  </para>
  <para>
    Kernel runtime parameters can be set through
    <xref linkend="opt-boot.kernel.sysctl" />, e.g.
  </para>
  <programlisting language="bash">
boot.kernel.sysctl.&quot;net.ipv4.tcp_keepalive_time&quot; = 120;
</programlisting>
  <para>
    sets the kernel’s TCP keepalive time to 120 seconds. To see the
    available parameters, run <literal>sysctl -a</literal>.
  </para>
  <section xml:id="sec-linux-config-customizing">
    <title>Building a custom kernel</title>
    <para>
      You can customize the default kernel configuration by overriding
      the arguments for your kernel package:
    </para>
    <programlisting language="bash">
pkgs.linux_latest.override {
  ignoreConfigErrors = true;
  autoModules = false;
  kernelPreferBuiltin = true;
  extraStructuredConfig = with lib.kernel; {
    DEBUG_KERNEL = yes;
    FRAME_POINTER = yes;
    KGDB = yes;
    KGDB_SERIAL_CONSOLE = yes;
    DEBUG_INFO = yes;
  };
}
</programlisting>
    <para>
      See <literal>pkgs/os-specific/linux/kernel/generic.nix</literal>
      for details on how these arguments affect the generated
      configuration. You can also build a custom version of Linux by
      calling <literal>pkgs.buildLinux</literal> directly, which
      requires the <literal>src</literal> and <literal>version</literal>
      arguments to be specified.
    </para>
    <para>
      To use your custom kernel package in your NixOS configuration, set
    </para>
    <programlisting language="bash">
boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
</programlisting>
    <para>
      Note that this method will use the common configuration defined in
      <literal>pkgs/os-specific/linux/kernel/common-config.nix</literal>,
      which is suitable for a NixOS system.
    </para>
    <para>
      If you already have a generated configuration file, you can build
      a kernel that uses it with
      <literal>pkgs.linuxManualConfig</literal>:
    </para>
    <programlisting language="bash">
let
  baseKernel = pkgs.linux_latest;
in pkgs.linuxManualConfig {
  inherit (baseKernel) src modDirVersion;
  version = &quot;${baseKernel.version}-custom&quot;;
  configfile = ./my_kernel_config;
  allowImportFromDerivation = true;
}
</programlisting>
    <note>
      <para>
        The build will fail if <literal>modDirVersion</literal> does not
        match the source’s <literal>kernel.release</literal> file, so
        <literal>modDirVersion</literal> should remain tied to
        <literal>src</literal>.
      </para>
    </note>
    <para>
      To edit the <literal>.config</literal> file for Linux X.Y, proceed
      as follows:
    </para>
    <programlisting>
$ nix-shell '&lt;nixpkgs&gt;' -A linuxKernel.kernels.linux_X_Y.configEnv
$ unpackPhase
$ cd linux-*
$ make nconfig
</programlisting>
  </section>
  <section xml:id="sec-linux-config-developing-modules">
    <title>Developing kernel modules</title>
    <para>
      When developing kernel modules it’s often convenient to run
      edit-compile-run loop as quickly as possible. See below snippet as
      an example of developing <literal>mellanox</literal> drivers.
    </para>
    <programlisting>
$ nix-build '&lt;nixpkgs&gt;' -A linuxPackages.kernel.dev
$ nix-shell '&lt;nixpkgs&gt;' -A linuxPackages.kernel
$ unpackPhase
$ cd linux-*
$ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules
# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko
</programlisting>
  </section>
  <section xml:id="sec-linux-zfs">
    <title>ZFS</title>
    <para>
      It’s a common issue that the latest stable version of ZFS doesn’t
      support the latest available Linux kernel. It is recommended to
      use the latest available LTS that’s compatible with ZFS. Usually
      this is the default kernel provided by nixpkgs (i.e.
      <literal>pkgs.linuxPackages</literal>).
    </para>
    <para>
      Alternatively, it’s possible to pin the system to the latest
      available kernel version <emphasis>that is supported by
      ZFS</emphasis> like this:
    </para>
    <programlisting language="bash">
{
  boot.kernelPackages = pkgs.zfs.latestCompatibleLinuxPackages;
}
</programlisting>
    <para>
      Please note that the version this attribute points to isn’t
      monotonic because the latest kernel version only refers to kernel
      versions supported by the Linux developers. In other words, the
      latest kernel version that ZFS is compatible with may decrease
      over time.
    </para>
    <para>
      An example: the latest version ZFS is compatible with is 5.19
      which is a non-longterm version. When 5.19 is out of maintenance,
      the latest supported kernel version is 5.15 because it’s longterm
      and the versions 5.16, 5.17 and 5.18 are already out of
      maintenance because they’re non-longterm.
    </para>
  </section>
</chapter>