Improving custom configuration for alternate kernels

An acquaintance was having trouble getting custom kernel configuration to work on NixOS when they used anything other than stock kernels, e.g. Linux-libre. boot.kernelPatches was being set, but it just didn’t seem to get plumbed through. After some digging, I figured out why: Setting boot.kernelPackages = pkgs.linuxPackages_latest-libre; will cause boot.kernelPatches to do nothing: changing it won’t even cause a rebuild. The reason why is because of how boot.kernelPatches gets applied:

      apply = kernelPackages: kernelPackages.extend (self: super: {
        kernel = super.kernel.override (originalArgs: {
          inherit randstructSeed;
          kernelPatches = (originalArgs.kernelPatches or []) ++ kernelPatches;
          features = lib.recursiveUpdate super.kernel.features features;

When using Linux-libre this just silently does absolutely nothing, because deblobKernel calls callPackage which of course calls callPackageWith that calls makeOverridable, so when we try to override the kernel we’re really overriding the linux-libre wrapper and the arguments go silently unused.

This is pretty unfortunate. Anybody have suggestions? I think it’d be great to prevent future pain here. Here’s what I’ve thought of so far:

  • Remove callPackage usage. Works but not ideal. Doesn’t prevent users from accidentally running into the same problem with their own kernel overrides.
  • Carry kernelPatches forward. I guess this would make boot.kernelPatches function but it seems even more confusing because you wouldn’t be able to see or modify the kernelPatches that the Linux kernel derivation itself has. Also doesn’t stop the user from making the same mistake.
  • Spitballing, but… somehow copy override to overrideKernel for kernels? I am not 100% sure if this works and isn’t broken, but the idea is that no matter how many times makeOverridable gets called, it would still be possible to access the original override for the kernel derivation itself.

I would love to get this fixed in a future NixOS release…

P.S.: It also is probably worth mentioning that if you make a typo in boot.kernelPatches, e.g. structuredExtraConfig instead of extraStructuredConfig, it also doesn’t cause an error. I’m guessing that’s because the type of boot.kernelPatches is type = types.listOf types.attrs and so extra unused attributes don’t cause any errors. I don’t have advanced enough knowledge of the type-checking logic to try to fix this, but that too would be a great rough edge to smooth out.


Yes, this drives me nuts too. I opened a PR to fix it a year ago:

and the response I got from the package maintainer was… basically bikeshedding over which of the two spellings was better than the other. Which kinda misses the point that whichever one we pick, there needs to be an error or other feedback if the user uses the other one by mistake.

The nixpkgs kernel expressions have been a source of frustration for me for a long time. Part of the problem is that we never built a declarative eval-time interface to Kconfig… the constraints are known only to a perl script which doesn’t run until build time. The solution to this is kconfig-cli; when it’s ready I plan to start over with new kernel expressions; I think the current ones are beyond hope of salvaging.


is there somewhere i can read more about this? it sounds exciting!

1 Like