Table of Contents
- Prerequisites
- Getting the Kernel Source Code
- Choosing a Kernel Version
- Configuring the Kernel
- 4.1 Using
make menuconfig - 4.2 Reusing an Existing Configuration
- 4.3 Key Configuration Tips
- 4.1 Using
- Building the Kernel
- Installing Modules and the Kernel
- Updating the Bootloader
- Testing the New Kernel
- Troubleshooting Common Issues
- Cleaning Up
- Conclusion
- References
Prerequisites
Before starting, ensure your system has the tools and dependencies required to build the kernel. Most modern Linux distributions will need the following packages:
For Debian/Ubuntu-based systems:
sudo apt update && sudo apt install -y \
build-essential libncurses-dev bison flex libssl-dev libelf-dev \
git dwarves zstd # dwarves for BTF debugging; zstd for compression
For Fedora/RHEL-based systems:
sudo dnf install -y \
gcc gcc-c++ make ncurses-devel bison flex openssl-devel elfutils-libelf-devel \
git dwarves zstd
For Arch Linux:
sudo pacman -Syu --needed \
base-devel ncurses bison flex openssl elfutils git dwarves zstd
Note: Ensure you have at least 20GB of free disk space and 4GB+ of RAM (8GB+ recommended for faster builds).
Getting the Kernel Source Code
The official Linux kernel source is hosted on kernel.org. You can either download a tarball or clone the source code using git (recommended for easier updates).
Option 1: Clone via Git (Recommended)
The Linux kernel Git repository is large (~2GB), but cloning it lets you easily switch between versions:
git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
cd linux
Option 2: Download a Tarball
If you prefer not to use git, download a stable kernel tarball from kernel.org. For example, to download version 6.6.3 (LTS):
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.3.tar.xz
tar -xf linux-6.6.3.tar.xz
cd linux-6.6.3
Choosing a Kernel Version
Kernel.org categorizes releases into several types. For most users, Long-Term Support (LTS) kernels are the best choice due to their stability and extended maintenance (5+ years for recent LTS versions).
- Stable: Updated frequently with bug fixes but not maintained long-term.
- LTS: Stable, with security updates for years (e.g., 6.6.x, 6.1.x).
- Mainline: Cutting-edge, for testing new features (not recommended for production).
Check the kernel release schedule to pick the right version. For this guide, we’ll use an LTS kernel (e.g., 6.6.3).
Configuring the Kernel
The kernel configuration step determines which features, drivers, and subsystems are included in your custom kernel. This is critical: including unnecessary components increases bloat, while excluding essential ones can break your system.
Step 1: Start with a Baseline Configuration
Instead of configuring from scratch, reuse your distribution’s existing kernel config as a starting point. This ensures compatibility with your hardware and software.
Method 1: Use /boot/config-* (Most Distributions)
Your running kernel’s configuration is stored in /boot. Copy it to the kernel source directory:
zcat /proc/config.gz > .config # Alternative: copies the *running* kernel's config
# OR (if /proc/config.gz is missing):
cp /boot/config-$(uname -r) .config
Method 2: Use make localmodconfig (Minimalist)
For a stripped-down config, localmodconfig generates a config based only on currently loaded modules:
make localmodconfig # Answers "yes" to all prompts with Enter
Step 2: Refine the Configuration with make menuconfig
Use make menuconfig to tweak the baseline config. This launches a text-based interface to enable/disable features:
make menuconfig
Navigation Tips:
- Use arrow keys to move,
Enterto select, andEscto go back. - Press
?for help on a selected option. Y= Build feature directly into the kernel (not as a module).M= Build as a loadable module (recommended for most drivers to save space).N= Disable the feature.
Key Options to Review:
- Processor Type and Features: Match your CPU architecture (e.g.,
x86_64,ARM64). EnableSymmetric Multi-Processingfor multi-core CPUs. - Device Drivers: Include drivers for your storage (e.g., NVMe, SATA), GPU, and network hardware.
- File Systems: Enable support for your root filesystem (e.g.,
ext4,btrfs,XFS). - Security Options: Enable
Control Group Support(for systemd) andSecure Bootif needed. - Kernel Hacking: Disable
Kernel Debuggingunless you’re debugging (increases size).
When done, save the config (default: .config) and exit.
Step 3: Update the Config for New Kernel Versions
If you’re upgrading from an older kernel version, run make olddefconfig to automatically resolve new options (uses default values for new features):
make olddefconfig
Building the Kernel
With the config finalized, build the kernel. This step compiles the kernel image, modules, and associated files.
Optimize Build Speed
Use the -j flag to parallelize the build (replace N with the number of CPU cores + 1 for faster builds). For an 8-core CPU:
make -j9 # 8 cores + 1 = 9 jobs
What Happens During the Build?
vmlinux: The raw kernel binary (uncompressed).arch/x86/boot/bzImage: The compressed kernel image (loaded by the bootloader).- Modules: Stored in
modules/(later installed to/lib/modules/).
Installing Modules and the Kernel
After building, install the kernel modules and the kernel itself.
Step 1: Install Modules
Modules are loadable components (e.g., drivers) that extend kernel functionality. Install them to /lib/modules/:
sudo make modules_install
This creates a directory like /lib/modules/6.6.3-custom/ (replace 6.6.3-custom with your kernel version).
Step 2: Install the Kernel
Install the kernel image, System.map (symbol table), and config file to /boot:
sudo make install
This also generates an initramfs (initial RAM filesystem) to load critical drivers before the root filesystem mounts.
Updating the Bootloader
Your bootloader (e.g., GRUB, systemd-boot) needs to detect the new kernel to list it in the boot menu.
For GRUB (Most Distributions: Ubuntu, Fedora, Debian)
Update GRUB’s configuration to include the new kernel:
sudo update-grub # Debian/Ubuntu
# OR (Fedora/RHEL):
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
For systemd-boot (Arch Linux, Fedora with UEFI)
If using systemd-boot (common on UEFI systems), copy the kernel and initramfs to /boot/EFI/Linux/ and create a loader entry:
# Replace "6.6.3-custom" with your kernel version
sudo cp /boot/vmlinuz-6.6.3-custom /boot/EFI/Linux/
sudo cp /boot/initramfs-6.6.3-custom.img /boot/EFI/Linux/
# Create a loader entry (e.g., /boot/loader/entries/custom.conf)
sudo nano /boot/loader/entries/custom.conf
Add this content to custom.conf (adjust paths for your system):
title Custom Linux 6.6.3
linux /vmlinuz-6.6.3-custom
initrd /initramfs-6.6.3-custom.img
options root=UUID=your_root_partition_uuid rw quiet
Find your root partition’s UUID with blkid.
Testing the New Kernel
Reboot your system and select the custom kernel from the boot menu (e.g., “Custom Linux 6.6.3” in GRUB).
Verify the Kernel Version
After booting, confirm the new kernel is running:
uname -r # Should output "6.6.3-custom" (or your version)
Check for Issues
- Run
dmesg | grep -i errorto look for hardware/driver errors. - Test critical features: network, sound, graphics, and storage.
Troubleshooting Common Issues
1. System Fails to Boot
- Fix: Reboot and select your old kernel from the GRUB menu. Check logs with
journalctl -k -b -1(boot log from last failed attempt).
2. Missing Drivers/Hardware Not Working
- Fix: Reboot to the old kernel, re-run
make menuconfig, and enable the missing driver (e.g., Wi-Fi, GPU). Rebuild and reinstall.
3. Initramfs Errors
- Fix: Regenerate the initramfs manually:
sudo update-initramfs -c -k 6.6.3-custom # Replace with your kernel version
4. “No Space Left on Device”
- Fix: Clean up old kernels in
/boot(usesudo apt autoremoveon Debian/Ubuntu) or free space elsewhere.
Cleaning Up
Building the kernel generates large temporary files. Clean them up to save space:
make clean # Removes object files (keeps .config)
# OR (to reset completely, including .config):
make mrproper
Delete the kernel source directory if you don’t need it anymore:
cd .. && rm -rf linux-6.6.3 # Replace with your source directory
Conclusion
Building a custom Linux kernel is a rewarding project that lets you tailor your system to your needs. While it requires time and patience, the benefits—faster boot times, better hardware support, and a deeper understanding of Linux—are well worth it. Start with small tweaks, test thoroughly, and refer to the references below for advanced configurations.