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