dotlinux blog

Custom Kernels in Ubuntu/Debian – How to Build, Install, and Optimize

The Linux kernel is the core of your operating system, managing hardware resources, enabling communication between software and hardware, and ensuring system stability. While Ubuntu and Debian ship with precompiled, "generic" kernels optimized for broad compatibility, there are scenarios where a custom kernel makes sense:

  • Hardware-specific support: Enabling drivers for rare or cutting-edge hardware not included in the stock kernel.
  • Performance optimization: Tweaking settings (e.g., CPU scheduling, I/O priorities) for gaming, server workloads, or low-latency audio/video production.
  • Security hardening: Disabling unused features to reduce attack surface or enabling security patches not yet in the stock kernel.
  • Learning/experimentation: Understanding kernel internals by modifying and rebuilding the source code.

This guide will walk you through building, configuring, installing, and troubleshooting a custom kernel on Ubuntu or Debian. We’ll cover two methods: the traditional make workflow and Debian’s make-kpkg (for easier package management).

2026-01

Table of Contents#

  1. Prerequisites
  2. Getting the Kernel Source Code
  3. Configuring the Kernel
  4. Building the Kernel
  5. Installing the Custom Kernel
  6. Testing and Validation
  7. Troubleshooting Boot Issues
  8. Cleaning Up
  9. References

Prerequisites#

Before starting, ensure your system meets these requirements:

  • Ubuntu/Debian system: Tested on Ubuntu 22.04 LTS and Debian 12.
  • Disk space: At least 30 GB free (kernel sources + build artifacts).
  • Time: Building takes 30 minutes to 2+ hours (varies by CPU cores).
  • Dependencies: Install build tools and libraries:
    sudo apt update && sudo apt install -y \  
      build-essential libncurses-dev libssl-dev libelf-dev \  
      bison flex dwarves fakeroot git  
  • Root access: You’ll need sudo privileges for installation steps.

Getting the Kernel Source Code#

You can obtain kernel sources from three places:

Ubuntu and Debian package their kernel sources, ensuring compatibility with system tools.

  1. Enable source repositories:
    Edit /etc/apt/sources.list (with sudo nano /etc/apt/sources.list) and uncomment lines starting with deb-src.

  2. Fetch the source for your current kernel:

    # Get the version of your running kernel  
    uname -r  # Output: e.g., 5.15.0-78-generic  
     
    # Fetch the source (replace <version> with output from uname -r)  
    sudo apt update  
    apt source linux-image-$(uname -r)  

    This creates a directory like linux-5.15.0 in your current folder.

Option 2: Latest Stable Kernel (kernel.org)#

For the newest features, download from kernel.org:

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.5.5.tar.xz  
tar -xf linux-6.5.5.tar.xz  
cd linux-6.5.5  

Option 3: Git Repository (Bleeding Edge)#

For development versions, clone the Linux kernel git repo:

git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git  
cd linux  
git checkout v6.5.5  # Checkout a specific stable version  

Configuring the Kernel#

Kernel configuration determines which features, drivers, and optimizations are included. Start with a baseline config (e.g., your current kernel’s settings) and tweak from there.

Step 1: Copy the Current Kernel Config#

Use your existing kernel’s config as a starting point to avoid breaking hardware support:

# From the kernel source directory  
cp /boot/config-$(uname -r) .config  

Step 2: Launch the Configuration Tool#

Edit the config with menuconfig (text-based) or xconfig/gconfig (GUI):

make menuconfig  # Text-based (recommended for servers/SSH)  
# OR  
make xconfig    # Qt-based GUI (needs X11)  
# OR  
make gconfig    # GTK-based GUI  

Key Configuration Options to Tweak#

Here are common optimizations (navigate using arrow keys; press ? for help):

  • General SetupLocal version - append to kernel release: Add a custom suffix (e.g., -mycustom) to identify your kernel (e.g., 6.5.5-mycustom).
  • Processor type and featuresProcessor family: Select your CPU (e.g., "Intel Core2/Newer Xeon" or "AMD Opteron/Athlon64").
  • Processor type and featuresPreemption Model:
    • "No Forced Preemption" (server workloads, maximum throughput).
    • "Preemptible Kernel (Low-Latency Desktop)" (desktop/gaming, better responsiveness).
  • Kernel FeaturesTimer frequency: Set to 1000 Hz (default is 250 Hz) for lower latency (caution: may increase power usage).
  • Device Drivers: Disable unused hardware support (e.g., "Network device support" → "Wireless LAN" → uncheck drivers for Wi-Fi cards you don’t own).
  • File systems: Disable unused filesystems (e.g., Btrfs, XFS if using only ext4).
  • Security options: Enable "Control Flow Integrity" (CFI) or "Kernel Address Space Layout Randomization (KASLR)" for hardening.

After tweaking, save the config (default filename .config) and exit.

Building the Kernel#

Choose one of these methods to build the kernel. make-kpkg (Debian-style) is recommended for easier installation/removal.

Method 1: Traditional make Workflow#

This method builds and installs the kernel directly.

Step 1: Clean Previous Build Artifacts (If Reconfiguring)#

If you’ve built before, clean old files:

make clean        # Removes most build files (keeps .config)  
# OR  
make mrproper     # Removes .config and all build files (start fresh)  

Step 2: Build the Kernel and Modules#

Compile the kernel and modules. Use -jN with N = number of CPU cores + 1 for faster builds:

# Check CPU cores: nproc → e.g., 8 cores → use -j9  
make -j$(nproc)  
make modules -j$(nproc)  # Builds kernel modules  

Step 3: Install Modules and Kernel#

sudo make modules_install  # Install modules to /lib/modules/<version>  
sudo make install          # Copy kernel image, System.map, and update GRUB  

make-kpkg builds .deb packages, simplifying installation, removal, and dependency management.

Step 1: Build the Debian Package#

From the kernel source directory:

# -jN: parallel jobs (use nproc for optimal speed)  
# --initrd: generate initramfs (required for most systems)  
# --revision: custom version suffix (e.g., "mycustom1")  
fakeroot make-kpkg -j$(nproc) --initrd --revision=mycustom1 kernel_image kernel_headers  

This generates two .deb files in the parent directory:

  • linux-image-6.5.5-mycustom1_amd64.deb (kernel binary)
  • linux-headers-6.5.5-mycustom1_amd64.deb (headers for module compilation)

Installing the Custom Kernel#

If Using make install (Method 1):#

The make install step already copies files and updates GRUB. Skip to testing.

If Using make-kpkg (Method 2):#

Install the .deb packages:

# From the directory containing the .deb files  
sudo dpkg -i linux-image-6.5.5-mycustom1_amd64.deb  
sudo dpkg -i linux-headers-6.5.5-mycustom1_amd64.deb  

Update GRUB (Critical!)#

Ensure GRUB recognizes the new kernel:

sudo update-grub  

Testing and Validation#

Reboot your system and select the custom kernel from the GRUB menu (hold Shift during boot if GRUB doesn’t appear).

Verify the Kernel Version#

After logging in, confirm the new kernel is running:

uname -r  # Should output: 6.5.5-mycustom1 (or your custom suffix)  

Check Hardware and Functionality#

Test critical hardware (network, sound, graphics) and workloads:

  • ping google.com (network)
  • Play audio/video (sound card)
  • Run glxinfo | grep "OpenGL renderer" (graphics drivers)

Monitor Performance/Stability#

Use tools like htop (CPU/memory), iostat (disk I/O), or dmesg (kernel logs) to check for errors:

dmesg | grep -i error  # Look for critical issues  

Troubleshooting Boot Issues#

If the system fails to boot:

Step 1: Revert to the Old Kernel#

Reboot and select your previous kernel from the GRUB "Advanced options" menu.

Step 2: Diagnose the Problem#

  • Check GRUB entries: grep menuentry /boot/grub/grub.cfg
  • View kernel logs: journalctl -b -1 (logs from last boot)
  • Missing initramfs: Regenerate with sudo update-initramfs -c -k 6.5.5-mycustom1
  • Incompatible drivers: Rebuild with make menuconfig and re-enable critical drivers (e.g., storage controllers).

Step 3: Uninstall the Custom Kernel#

If all else fails, remove the custom kernel:

  • If using make-kpkg (Debian packages):

    sudo apt remove linux-image-6.5.5-mycustom1 linux-headers-6.5.5-mycustom1  
  • If using make install:
    Manually delete kernel files:

    sudo rm -rf /boot/vmlinuz-6.5.5-mycustom1 \  
                /boot/initrd.img-6.5.5-mycustom1 \  
                /lib/modules/6.5.5-mycustom1  
    sudo update-grub  

Cleaning Up#

Free disk space by removing build artifacts and old kernels.

Remove Source Build Files#

From the kernel source directory:

make clean  # Removes object files (keeps .config)  
# OR  
make mrproper  # Removes all build files and .config (start fresh)  

Remove Old Kernels#

Keep only the 2-3 most recent kernels:

# List installed kernels  
dpkg --list | grep linux-image  
 
# Remove old kernels (replace <version> with the kernel to delete)  
sudo apt remove linux-image-<version> linux-headers-<version>  
sudo apt autoremove  # Clean up dependencies  

References#

By following these steps, you’ve built and installed a custom kernel tailored to your needs. Whether optimizing for performance, adding hardware support, or learning, this process empowers you to take full control of your system’s core. Happy hacking! 🐧