julian@hub:~/blog$ cat cachyos-kernel.md

Running CachyOS Kernels on NixOS Without Compiling.

If you've tried running CachyOS's kernel on NixOS, chances are you ran nixos-rebuild switch, saw your fans spin up to 100%, and realized Nix decided to compile the entire Linux kernel from source.

The CachyOS kernel with the BORE (Burst-Oriented Response Enhancer) scheduler is great for desktop responsiveness and frame times in games, but nobody wants a 45-minute build on every kernel point release.

Here is the exact setup I use on my desktop (junixos) to pull pre-built kernel binaries directly from the Attic cache in under 10 seconds.

The Trap: Why Nix Tries to Build It Locally

When adding flake inputs, muscle memory usually tells you to add inputs.nixpkgs.follows = "nixpkgs".

With kernel flakes, this is what breaks the cache. Because kernel packages depend strictly on the exact toolchain and nixpkgs revision used by the CI builder, overriding nixpkgs changes the derivation hash. Nix sees that your local derivation hash doesn't match the remote cache, assumes it's custom, and starts building from source.

Step 1: Declare the Flake Input (Without Follows)

In your flake.nix, import nix-cachyos-kernel and pass it down via specialArgs:

# flake.nix
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

    # Do NOT add 'inputs.nixpkgs.follows = "nixpkgs"' here!
    nix-cachyos-kernel.url = "github:xddxdd/nix-cachyos-kernel/release";
  };

  outputs = { self, nixpkgs, nix-cachyos-kernel, ... }@inputs: {
    nixosConfigurations."junixos" = nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [
        ./hosts/junixos/configuration.nix
      ];
    };
  };
}

Step 2: Add the Binary Cache & Kernel Module

Next, we tell Nix where to fetch the pre-built binaries and provide the public signing key. I keep this modular in my kernel.nix so I can toggle between CachyOS, standard latest, or LTS:

# modules/nixos/kernel.nix
{ config, lib, pkgs, inputs, ... }:
let
  cfg = config.custom.system.kernel;
in {
  options.custom.system.kernel = lib.mkOption {
    type = lib.types.enum [ "cachyos" "latest" "lts" ];
    default = "latest";
  };

  config = lib.mkMerge [
    (lib.mkIf (cfg == "cachyos") {
      # Use the pre-built CachyOS kernel
      boot.kernelPackages =
        inputs.nix-cachyos-kernel.legacyPackages.${pkgs.stdenv.hostPlatform.system}.linuxPackages-cachyos-bore;

      # Binary cache substituter and public key
      nix.settings = {
        substituters = [ "https://attic.xuyh0120.win/lantian" ];
        trusted-public-keys = [
          "lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc="
        ];
      };
    })

    (lib.mkIf (cfg == "latest") {
      boot.kernelPackages = pkgs.linuxPackages_latest;
    })
  ];
}

Step 3: Enable It in Your Host Config

Now inside your machine configuration, just set:

# hosts/junixos/configuration.nix
{
  custom.system.kernel = "cachyos";
}

Run nixos-rebuild switch --flake .#junixos. Instead of a long compile step, you'll see Nix substitute the binary packages straight from the cache and finish the rebuild in a few seconds.

Does It Actually Make a Difference?

On desktop setups running high refresh rate Wayland/Hyprland sessions and games, BORE does a noticeably better job keeping UI interactions and framerates smooth when the CPU is under background load (like heavy cargo or nix builds while gaming).

You can check out the full flake setup in my NixOS-Dotfiles repo.