The *correct* way to override the latest kernel config

i was wondering what is currently the right way to override the latest linux kernel with extra configuration.

My configuration currently looks like this:

{
  boot.kernelPackages = pkgs.linuxPackages_4_16;
  nixpkgs.config.packageOverrides = pkgs: {
    linux_4_16 = pkgs.linux_4_16.override {
        extraConfig = ''
          LIRC y
        '';
    };
  };
}

My code snippet pins the linuxPackages version to 4.16 ,however i would like to follow the channel and use linuxPackages_latest as my kernel package.
Is there a way to override the linux kernel used in linuxPackages_latest ?

Cheers!

1 Like

There is a boot.kernelPatches option you can (mis-)use to add additional configuration:

{ lib, ... }:

{
  boot.kernelPatches = lib.singleton {
    name = "enable-lirc";
    patch = null;
    extraConfig = ''
      LIRC y
    '';
  };
}

This will affect the kernel you’re using in boot.kernelPackages.

2 Likes

Just for the sake of learning: why can’t you just use linuxPackage_latest/linux_latest instead of linuxPackages_4_16/linux_4_16 in the above snippet ?

Sure, wasn’t that what the original poster already suggested?

Like eg.:

{ pkgs, lib, ... }:

{
  boot.kernelPackages = pkgs.linuxPackages_latest;
  boot.kernelPatches = lib.singleton {
    name = "enable-lirc";
    patch = null;
    extraConfig = ''
      LIRC y
    '';
  };
}

Then you have the latest kernel with CONFIG_LIRC enabled.

1 Like

OP’s last question was Is there a way to override the linux kernel used in linuxPackages_latest ? The obvious answer is “Yes, override linux_latest”.
This post seemed to imply that it does not work, or is incorrect.

AFAIK, the following should work and is at least a correct way to achieve his goal. If OP finds this unsatisfying, or if it does not work, I wanted to know why, just by sheer curiosity.

{
  boot.kernelPackages = pkgs.linuxPackages_latest;
  nixpkgs.config.packageOverrides = pkgs: {
    linux_latest = pkgs.linux_latest.override {
        extraConfig = ''
          LIRC y
        '';
    };
  };
}

Thanks for all the replies, i found the issue with the code i tried before.
I incorrectly assumed that pkgs.linux maps to the kernel which is used in boot.kernelPackages - pkgs.linux_latest is the correct thing to use here.

Special thanks to azlig for boot.kernelPatches which seems to be a cleaner approach than overriding the kernel config via packageOverrides.

Ah, so now I’m getting what @layus was referring to :bulb: (hopefully).

So let’s say you want to override the kernel in linuxPackages_latest, independent of NixOS.

Let’s look at how linuxPackages_latest is defined:

{
  # ...
  # Here is the composition of all the kernel packages for the given kernel:
  linuxPackagesFor = kernel: lib.makeExtensible ...;
  # linuxPackages_latest is just an alias for the latest kernel version.
  linuxPackages_latest = linuxPackages_4_17;
  # This composes the kernel packages for linux_4_17, not it is NOT linux_latest:
  linuxPackages_4_17 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_4_17);
  # ... and linux_latest just refers to the kernel within previously
  # defined kernelPackages_latest
  linux_latest = linuxPackages_latest.kernel;
  # ...
}

So what this means is that we can’t simply override linux_latest and get a new linuxPackages_latest with the overrides. We would have to override linux_4_17 instead, which isn’t very practical if you want to stay on the latest kernel.

Instead, we need to override linuxPackages_latest, by using .extend (note the makeExtensible above):

{ lib, ... }:

{
  nixpkgs.overlays = lib.singleton (lib.const (super: {
    linuxPackages_latest = super.linuxPackages_latest.extend (lib.const (ksuper: {
      kernel = ksuper.kernel.override {
        extraConfig = ''
          LIRC y
        '';
      };
    }));
  }));
}
5 Likes

I stumbled into this same issue recently. It seems rather unintuitive / user-unfriendly. Is there a reason why nixpkgs doesn’t define linuxPackages_latest and linux_latest (and others, such as linuxPackages and linux) like this instead:

  linux_latest = linux_5_12;
  linuxPackages = linuxPackagesFor linux_latest;

Note that the equivalent of structuredExtraConfig is called extraStructuredConfig in kernelPatches:

{ lib, ... }:

{
  boot.kernelPatches = lib.singleton {
    name = "enable-lirc";
    patch = null;
    extraStructuredConfig = with lib.kernel; {
      LIRC = yes;
    };
  };
}
1 Like