Kahibaro
Discord Login Register

4.3.4 Compiling a custom kernel

Why (and When) You’d Compile Your Own Kernel

Compiling a custom kernel is about tailoring the Linux kernel to your exact needs instead of using a generic distribution kernel. Common reasons:

For most users, the distribution kernel is sufficient; compiling your own makes sense when you explicitly need something it doesn’t provide.

High-Level Workflow

Compiling a custom kernel on a typical distribution generally follows this pattern:

  1. Prepare the system (install build tools and kernel headers).
  2. Get kernel sources (from your distro or kernel.org).
  3. Start from an existing configuration (usually the distro’s config).
  4. Configure the kernel for your needs.
  5. Build the kernel and modules.
  6. Install modules and kernel image.
  7. Update bootloader (often automatic via distro tools).
  8. Boot and test the new kernel.
  9. Keep the old kernel as a fallback.

The details differ slightly between distributions, but the core steps are similar.

Preparing Your Build Environment

You should build on the same architecture and (ideally) same distribution you plan to run the kernel on.

Basic Requirements

You’ll typically need:

Installing build dependencies (examples)

On Debian/Ubuntu:

bash
sudo apt update
sudo apt install build-essential libncurses-dev bison flex libssl-dev \
                 libelf-dev bc dwarves

On Fedora:

bash
sudo dnf groupinstall "Development Tools"
sudo dnf install ncurses-devel bison flex elfutils-libelf-devel openssl-devel \
                 bc dwarves

On Arch Linux:

bash
sudo pacman -S base-devel ncurses bc flex bison openssl zstd

Check the kernel documentation (Documentation/process/changes.rst in the source tree) for an up‑to‑date list of required tools.

Obtaining Kernel Sources

You have two main options:

1. Distro-Provided Kernel Source

Pros: integrates better with your distribution’s tooling, patches, and configuration.

Examples:

bash
  sudo apt install linux-source
  cd /usr/src
  tar xf linux-source-*.tar.xz
  cd linux-source-*
bash
  sudo dnf install kernel-devel kernel-src
  # Sources commonly under /usr/src/kernels or /usr/src

You can use the linux package’s PKGBUILD or asp to fetch source and patch set.

2. Upstream Kernel from kernel.org

Pros: latest mainline or LTS kernels, unmodified by distros.

bash
cd ~/src
mkdir -p kernel && cd kernel
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.*/linux-6.*.tar.xz
tar xf linux-6.*.tar.xz
cd linux-6.*/

Choose an LTS kernel for stability unless you specifically need mainline.

Starting from an Existing Configuration

Using your distribution’s existing kernel configuration is the safest starting point. It tends to include all necessary drivers for your hardware and distro specifics.

Common ways to get the current config:

Example:

bash
cp /boot/config-$(uname -r) .config

This imports your current kernel’s configuration into the new source tree.

To sync your .config with any new options introduced by a newer kernel:

bash
make oldconfig

This will prompt you for options that didn’t exist in the old kernel; you can usually accept the defaults unless you specifically need something.

Kernel Configuration Interfaces

All configuration interfaces produce/update the .config file in the kernel source directory; they just give you different ways to edit it.

Text-Based Menu: `menuconfig`

Requires libncurses dev libraries.

bash
make menuconfig

You get a hierarchical menu. Each item can be:

Relevant options for custom builds:

Graphical Interfaces: `xconfig` and `gconfig`

If you have a graphical environment:

bash
make xconfig   # Qt-based
# or
make gconfig   # GTK-based

These provide a GUI to navigate options. They’re convenient when you’re unfamiliar with option names.

Noninteractive Updates: `oldconfig` and `defconfig`

This is useful when doing minor version bumps with minimal changes.

Key Configuration Decisions

You can easily break booting if you disable the wrong thing. Focus on:

Built-In vs Module

A safe rule: if you’re not sure whether something is required for boot, keep the distro’s choice (usually y or m) and don’t switch it to n.

CPU and Optimization

Under Processor type and features:

Filesystems and Storage

Ensure support for:

Network and Drivers

If you rely on network-booting or remote access for administration, ensure relevant drivers and options remain enabled.

Building the Kernel

Once the .config is ready, you can compile.

Parallel Build

Use all CPU cores for speed (e.g., -j$(nproc)):

bash
make -j"$(nproc)"

This builds:

Build times depend on hardware and config: from minutes to an hour+.

Building Only Modules (Optional)

To recompile modules after config changes:

bash
make modules -j"$(nproc)"

But normally you just run plain make, which includes modules.

Installing Modules and Kernel Image

Installing Modules

As root:

bash
sudo make modules_install

This installs compiled modules into /lib/modules/<kernel-version>/.

Installing the Kernel and Updating Bootloader

Most distros recognize make install and perform the correct steps:

bash
sudo make install

Typically, this will:

On Debian/Ubuntu-style systems that prefer packages, an alternative is to use make deb-pkg (see below) and install .deb packages.

Creating and Using an initramfs

Many systems rely on an initramfs to provide drivers and scripts needed during early boot (e.g., encrypted disks, LVM). If your distro scripts don’t automatically build one for your custom kernel, you may have to:

bash
  sudo update-initramfs -c -k $(make kernelrelease)
bash
  sudo dracut -f /boot/initramfs-$(make kernelrelease).img $(make kernelrelease)

The exact command depends on your distribution. Ensure the initramfs filename matches what your bootloader entry expects.

Using Distro-Style Kernel Packages

Instead of bare make install, you can build native packages, which integrates better with your package manager and simplifies removal.

Debian/Ubuntu: `make deb-pkg`

From the kernel source tree:

bash
make -j"$(nproc)"
make deb-pkg -j"$(nproc)"

This creates .deb packages in the parent directory (e.g., ../linux-image-...deb, ../linux-headers-...deb). Install them with:

bash
cd ..
sudo dpkg -i linux-image-*.deb linux-headers-*.deb

The install scripts will automatically:

RPM-Based: `make rpm-pkg`

On Fedora/RHEL-like systems:

bash
make rpm-pkg -j"$(nproc)"

This produces RPMs (often in ~/rpmbuild/RPMS/), which you can install with dnf or rpm -i.

Managing Multiple Kernels Safely

You almost never want to replace your distro kernel completely. Instead, install your custom kernel alongside it.

Best practices:

If boot fails with the new kernel, reboot and select the old kernel from the bootloader menu.

Bootloader Entries and Selection

After installing the new kernel:

  1. Check /boot for files like:
    • vmlinuz-6.6.1-custom
    • initrd.img-6.6.1-custom (or similar)
  2. Check that the bootloader configuration was updated:
    • GRUB: /boot/grub/grub.cfg (generated from /etc/grub.d and /etc/default/grub).
    • Some systems use grub2-mkconfig during install.

If necessary, regenerate GRUB config manually (example on Debian/Ubuntu):

bash
sudo update-grub

Or on some RPM-based systems:

bash
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

At the next boot, choose your custom kernel from the GRUB menu if it isn’t the default.

Verifying the New Kernel

Once booted, confirm you are running the intended kernel:

bash
uname -r

You should see the version (including any local suffix) you configured.

Verify that:

bash
  lsmod

Common Pitfalls and How to Avoid Them

Missing Root Filesystem or Disk Driver

Symptom: kernel panic at boot, complaining it can’t mount root.

Causes:

Mitigation:

Over-Aggressive Stripping of Options

Symptom: some hardware or features stop working unexpectedly.

Cause: disabling subsystems based on limited understanding of their purpose.

Mitigation:

Enabling Too Many Debug Options

Symptom: sluggish performance, large kernel image, full logs.

Cause: Kernel hacking options like kernel debugging, lock debugging, sanitizers, extra checks.

Mitigation:

Slow Rebuilds After Minor Changes

You don’t need to make clean for every small change; incremental builds track what changed.

For more drastic config changes or patching, consider:

bash
make clean
# or more thorough:
make mrproper

make mrproper removes .config, so back it up first if needed.

Tips for Efficient Kernel Development and Experimentation

bash
  sudo apt install ccache      # or equivalent on your distro
  export CC="ccache gcc"
  make -j"$(nproc)"
bash
  mkdir -p ../build-kernel
  make O=../build-kernel oldconfig
  make O=../build-kernel -j"$(nproc)"
  sudo make O=../build-kernel modules_install
  sudo make O=../build-kernel install

This is especially useful when building multiple kernels from the same source.

Cleaning Up and Reverting

If you decide to revert to only the distro kernel:

Always verify that a working kernel remains present in /boot and in your bootloader menu before deleting anything.

When to Avoid a Custom Kernel

Compiling your own kernel isn’t always appropriate, especially on:

In those cases, prefer vendor kernels or vendor-provided kernels with backported features, and use custom kernels only in lab/test environments.

Views: 118

Comments

Please login to add a comment.

Don't have an account? Register now!