As a systems researcher or developer, you may often find yourself needing to compile the Linux kernel from scratch—especially when customization is required. In this post, I’ll walk you through the process of building the kernel from source.
This guide is based on David Augustat’s tutorial, along with some additional notes and personal experience from my own kernel builds.
Step 1. Download the Kernel Source
First, grab the latest source from kernel.org. At the time of writing, the latest stable release is 6.16.1. Make sure xz
is installed before extracting the archive.
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.16.1.tar.xz
tar -I xz -xf linux-6.16.1.tar.xz
cd linux-6.16.1
Step 2. Install Build Dependencies
Before compiling, install the required development tools and libraries:
sudo apt update && sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev dwarves
Step 3. (Optional) Customize the Kernel Version String
If desired, you can change the kernel version string by editing the Makefile
at the top level. Keep in mind that many tools (such as your package manager) depend on uname -r
, so changes should be minimal. The safest field to tweak is EXTRAVERSION:
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 16
SUBLEVEL = 1
EXTRAVERSION = -Demo
NAME = Baby Opossum Posse
[...]
With this modification, the output of uname -r
will become:
6.16.1-Demo
Step 4. Configure the Build Options
The Linux kernel has thousands of configuration options, so we don’t want to set them one by one. Instead, we’ll reuse the configuration from our current kernel as a baseline.
cp -v /boot/config-$(uname -r) .
yes "" | make localmodconfig
According to Documentation/admin-guide/README.rst
, the make target localmodconfig
creates a new configuration based on the current one, but disables any unused modules. This results in a smaller, faster build while keeping everything you currently use. During this step, the build system may prompt you about new configuration options that didn’t exist in your original config. For each new option, hitting Enter accepts the default. Since there can be many prompts, piping yes ""
automatically feeds empty answers (i.e., just “Enter”) to every question, letting the defaults be applied without manual intervention.
Bonus: If you want to explore more build targets and configuration helpers, run:
make help
Step 5. Disable Kernel Signing (Required on Ubuntu/Debian)
Since we don’t have access to Debian/Canonical’s private signing keys, we need to disable signing. Otherwise, the build will fail.
scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
scripts/config --set-str CONFIG_SYSTEM_TRUSTED_KEYS ""
scripts/config --set-str CONFIG_SYSTEM_REVOCATION_KEYS ""
Note: Because this kernel won’t be signed, you must disable Secure Boot in your BIOS/UEFI settings to load it.
Step 6. Build the Kernel and Modules
Now we’re ready to compile. Use all available CPU cores for faster builds:
make -j$(nproc) &> build-kernel.log
-j$(nproc)
enables parallel builds using all logical cores. Redirecting output to build-kernel.log
prevents your terminal from being flooded and makes troubleshooting easier.
For example, to quickly find issues in the log:
grep "^make" build-kernel.log
grep -i "error" build-kernel.log
Step 7. Install Modules and Kernel
Once compilation completes, install the kernel modules and kernel image:
sudo make modules_install &> install-mods.log
sudo make install &> install-kernel.log
Step 8. Reboot and Verify
Finally, reboot into your new kernel:
sudo reboot
After restarting, confirm the active kernel version:
uname -r
If you see your customized version string, congratulations—you’ve successfully built and installed your own Linux kernel!
Conclusion. All-in-one Script
You can first manually download the Linux kernel source, extract the archive and put this script into the kernel source folder to automate the compilation and installation process.
#!/bin/bash
set -eu
echo "Installing dependencies..."
sudo apt update && sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev dwarves -y
echo "Cleaning builds..."
make clean
make distclean
echo "Configuring build options..."
cp -v /boot/config-$(uname -r) .config
yes "" | make localmodconfig &> build-config.log
scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
scripts/config --set-str CONFIG_SYSTEM_TRUSTED_KEYS ""
scripts/config --set-str CONFIG_SYSTEM_REVOCATION_KEYS ""
echo "Compiling kernel..."
make -j$(nproc) &> build-kernel.log
echo "Installing kernel modules..."
sudo make modules_install &> install-mods.log
echo "Installing kernel..."
sudo make install &> install-kernel.log
Comments NOTHING