How to build a custom Linux kernel from sources
Want to customize the kernel of your Linux distribution ? Enable or disable specific features ? In this post, you will learn how to compile your custom Linux Kernel and configure your system to boot from it.

Necessary tools
Have a look at the 'Documentation/process/changes.rst' file for minimal requirements for compiling linux kernel. Most of the required packages may already be installed on your system. Installing the following packages will ensure the minimum and other additional packages may be needed:
pkg-config
andg++
(C and C++ compiler)libncurses5-dev
in order to use some non GUI 'make' targets to generate the kernel configuration filelibssl-dev
for SSL/TLS libraries- And maybe other packages depending on which 'make' target we use to generate the kernel '.config' configuration file. Have a look at error messages when using those targets to know which package(s) to install
Kernel configuration
The kernel configuration file used for the compilation is named '.config' and includes configuration settings that control the behavior of the kernel we are going to build (features that will be included).
The '.config' file is generated using 'make targets', which represent scripts that are provided to ease kernel configuration parameters setup. Here is a list and description of some of the 'make targets' available for configuring the kernel before compilation:
defconfig
: create a default configuration based on the system type detectedoldconfig
: update an existing '.config' configuration file with only the new kernel featuresmenuconfig
: launch a text-based menu for configurationclean
: remove all the previously created object filesmrproper
: remove all the previously created object files and configuration settings from the '.config' file. Useful for starting over after a configuration file creationxconfig
: launch a GUI for configurationgconfig
: launch a GTK GUI for configuration
To use one of those targets:
# Command : make TARGET_NAME
# Example of using the menuconfig target
make menuconfig
Use 'make help' for information about all the available targets.
Kernel compilation and post-compilation files
The kernel source code files comes with the 'bzImage' make target to create a compressed kernel binary. Depending on the kernel version, the type of the compressed binary file will differ: gzip for version 2.6.x, bzip2 for version 3.x and xz for version starting from 4.x.
The 'make' command can be used without argument to create an uncrompressed kernel binary. Once the compilation command process exits successfully, the resulting kernel binary file can be found in 'arch/SYSTEM_ARCH/boot' (replace SYSTEM_ARCH with the corresponding architecture of the system you are building the kernel for: arm, arm64, x86....).
A 'System.map' file will also be created in the source code base directory. It is used for debugging the kernel and can optionally be placed inside the system '/boot' folder alongside the kernel binary file when configuring the system for booting into the newly created kernel.
Compilation examples
Create an uncrompressed kernel binary file
make clean
make
Create a crompressed kernel binary file
make clean
make bzImage
Creating RPM and DEB packages for quick and scaled installations
Simply use the following targets from the previously compiled kernel source code directory:
bindeb-pkg
: create a DEB package containing the kernel binarybinrpm-pkg
: create a RPM package containing the kernel binary
Here are examples:
# Create a DEB package for the kernel installation
make bindeb-pkg
# Create a RPM package for the kernel installation
make binrpm-pkg
After installing the previously created packages, you will have the following files (examples for the 5.6.11 kernel version) inside the system '/boot' directory and will be ready to boot into the newly compiled kernel:
config-5.6.11
: kernel configuration file parameters used for compilationSystem.map-5.6.11
: kernel debugging fileinitrd.img-5.6.11
: the inital RAM disk file. This is a in-memory (RAM) filesystem image containing some kernel modules binaries required for the kernel to read files on the underlying storage devices, in order to launch system initialization scripts like '/sbin/init' during bootvmlinuz-5.6.11
: kernel binary file
Linux Kernel binaries files mames generally start with 'vmlinuz' followed by the kernel version. This is a conventional naming recognized by almost every linux distributions and tools that deal with kernel images.
Compiling and installing standard kernel modules
Simply use the 'modules' and 'modules_install' targets as shown below:
make modules
make modules_install
After running the commands above, kernel modules configured as loadable inside the kernel '.config' configuration file will be compiled and installed inside the '/lib/modules/KERNEL_VERSION' directory.
The presence of modules for a specific kernel version inside that directory is a pre-requisite for creating an initial RAM disk file for that kernel as the tools used to create it looks for modules they need inside that directory. See the next section for more.
Initramfs and initrd files creation
'initramfs' (for deb-based systems) and 'initrd' (for rpm-based systems) are tools used to create an in-memory filesystem image containing some kernel modules binaries required for the kernel to read files on the underlying storage devices, in order to launch system initialization scripts like '/sbin/init' during boot.
'initramfs' and 'initrd' tools will look for modules that will be included inside the initial RAM disk in '/lib/modules/KERNEL_VERSION' directory. So make sure modules are available inside that folder for the kernel version you are creating an initial RAM disk for.
When working with the kernel source code, the 'make modules' and 'make modules_install' commands will compile and install modules inside the '/lib/modules/KERNEL_VERSION' directory.
The 'initramfs' tool configuration file can be found in '/etc/initramfs-tools/initramfs.conf'. That configuration file contains default parameters values that will be used when generating the initial RAM disk with the 'initramfs' command. If you want to include specific modules inside the initial RAM disk, put their
names inside the '/etc/initramfs-tools/modules' file (one name per line).
Here is a list of other interesting tools related to initial RAM disk files:
lsinitramfs
: list the content of an initial RAM diskupdate-initramfs
: used to create/update initial RAM disk files for specific kernel versions. When creating an intial RAM disk (with '-c' flag), specifying a version is mandatory. When creating/updating an initial RAM disk (with '-u' flag), the RAM disk file will by default be created/updated for the latest installed kernel on the system, and will be available inside the '/boot' directory. We also have options to remove/update old initial RAM disk files or replace them. Default configuration parameters used by the tool can be updated in '/etc/initramfs-tools/update-initramfs.conf'.
Examples
Initramfs/initrd RAM disk files use a conventional naming. Generally an initial RAM disk file will be named: 'initrd.img-KERNEL_VERSION'. Ex: initrd.img-5.6.11. That convention is used by the 'update-initramfs' tool.
- Create an initial RAM disk file with initramfs for the installed kernel in version 5.6.11
mkinitramfs -o /boot/initrd.img-5.6.11
- Create an initial RAM disk file inside the '/boot' folder with 'update-initramfs' for the 5.6.11 installed kernel. The created file will be automatically named 'initrd.img-5.6.11'. The '-b' flag can be used to change the destination directory where the file will be created.
update-initramfs -c -k 5.6.11
- Create an initial RAM disk file with 'initramfs' for the lastest available kernel on the system. Create the file inside the '/boot' folder by default. If the file already exists it will be updated.
update-initramfs -u
Preparing the system for booting with the newly created kernel
If you have created a specific linux distribution package for the kernel binary installation, you just have to install it:
# Debian based installation for kernel 5.6.11 DEB package
# created with 'make bindeb-pkg' from sources
dpkg -i linux-image-5.6.11_5.6.11-1_amd64.deb
If you have just finished compiling the kernel from sources, you have to do the following:
- Compile and install standard modules (required for the initial RAM disk generation with 'initramfs' or 'initrd' tools)
- Create the initial RAM disk file
- Copy the following files inside the '/boot' folder. Replace 'KERNEL_VERSION' with the kernel version number. Replace SYSTEM_ARCH with the system architecture. Source files paths are relative to the kernel source code base directory:
- '.config' to '/boot/config-KERNEL_VERSION'
- 'System.map-KERNEL_VERSION' to '/boot/System.map-KERNEL_VERSION'
- 'arch/SYSTEM_ARCH/boot/bzImage' to '/boot/vmlinuz-KERNEL_VERSION'
- Update your bootloader configuration. If you are using GRUB, simply run the 'update-grub' command. GRUB will automatically detect the new kernel files created inside '/boot' and create new menu entries to allow booting into those new kernels:
bash$ sudo update-grub
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.6.11
Found initrd image: /boot/initrd.img-5.6.11
Found linux image: /boot/vmlinuz-4.15.0-99-generic
Found initrd image: /boot/initrd.img-4.15.0-99-generic
Found memtest86+ image: /boot/memtest86+.elf
Found memtest86+ image: /boot/memtest86+.bin
Done
For more about GRUB, have a look at Linux GRUB legacy and GRUB2 essentials