- Compiling your own kernel allows you to optimize performance, security, and support. hardware adjusting modules, file systems, and specific options.
- The standard process includes installing dependencies, downloading sources from kernel.org, reusing the current configuration, and configuring with make menuconfig or xconfig.
- It is essential to compile and install the kernel and modules, correctly generate initramfs, and integrate the new kernel into GRUB to ensure a Boot cleansed.
- Maintaining older kernels and knowing how to roll back or remove a problematic kernel is key to safely experimenting on any distro.
Compile the kernel of Linux It's one of those tasks that separates the curious user from the one who wants to delve deep into the operating systemIt's not mandatory for using GNU/Linux on a daily basis, but it is a great way to better understand how your machine works, get the most out of the hardware, and fine-tune the system to your liking.
In this guide you will see, step by step, how Download, configure, compile, and install a Linux kernel from scratch. We'll cover Debian-based distributions (Debian, Ubuntu, Mint, and derivatives), as well as general concepts applicable to other families like Fedora or CentOS. We'll also explore why you might want to do this, what tools you'll need, how to reuse your current kernel configuration, how to adjust options for Docker or specific hardware, and how to revert if something goes wrong.
Why you might be interested in compiling your own kernel
Before touching anything, it's important to be clear about what you want: Compiling the kernel is not always necessaryBut there are several compelling reasons to do so.
- performance and efficiencyRemoving drivers and features you never use can make your system boot faster, use less RAM, and reduce latency under certain workloads.
- SecurityDisabling features or modules you don't need reduces the attack surface. A more minimalist kernel is, in many contexts, a more secure kernel.
- Support for specific hardwareSometimes your distribution doesn't yet include the driver you need, or it's disabled; by compiling your own kernel you can activate support specifically for your hardware (network cards, RAID, devices of storage uncommon, etc.).
- Special functionsYou might want to try a new task scheduler, specific features for virtualization, Docker, containers, BPF, io_uring, or any other advanced features that are not enabled by default.
- Learning and experimentationCompiling the kernel is a very straightforward way to Learn how a GNU/Linux system is organized internally, how the hardware is initialized and how the modules are integrated.
However, for a home user who just wants to turn on the computer, browse the internet, and little else, Compiling the kernel by hand is like using a cannon to kill flies.It's a long, delicate process, and it's normal to eat some food along the way. kernel panic Before fine-tuning it. If you like tinkering, go for it; if not, it's best to stick with the official packages for your distro.
What exactly is the Linux kernel?
The Linux kernel is the central component of the system: the software that sits between the hardware and the rest of the programsIt is responsible for managing memory, processes, file systems, input/output devices, network, security, and much more.
Linux started in 1991 as a personal project of Linus Torvalds to create a free kernel. Since then it has grown tremendously: today we're talking about tens of millions of lines of code, maintained by thousands of developers under the license GPLv2The system we usually call "Linux" is actually a combination of Linux kernel + GNU tools and other components who assemble the distribution.
When you compile a custom kernel, what you do is generate a binary (usually /boot/vmlinuz-version) plus a set of modules in /lib/modules/version, accompanied by files such as System.mapneighbourhood, config with the configuration used and the initial boot image (initrd or initramfs).
Basic tools needed to compile the kernel
To compile a Linux kernel from source, you need a complete development environment. On Debian, Ubuntu, and Mint systems, this typically involves installing build-essential and a number of additional libraries and utilities.
Many classic guides recommend sets like the following (You can adapt them according to your layout.):
- Minimal set in Debian/Ubuntu for a relatively modern kernel:
sudo apt-get install build-essential libncurses-dev bison flex libssl-dev libelf-dev libudev-dev libpci-dev libiberty-dev dkms openssl bc autoconf - Debian packaging environment to build kernel .deb packages:
sudo apt install autoconf automake autotools-dev bison build-essential dh-make debhelper debmake devscripts dpkg fakeroot file gfortran git gnupg fp-compiler lintian patch pbuilder perl quilt xutils-dev
In Fedora, CentOS and derivativesThe approach changes slightly, but the idea remains the same: install a set of development tools and libraries for configuration interfaces (text and graphical). For example, the following are commonly used commands of the style:
su -c 'yum groupinstall "Development Tools"'
su -c 'yum install ncurses-devel qt-devel unifdef'
Without these dependencies, the compilation will fail fairly quickly, so it's It is essential to have the environment ready before downloading the source code.
Where to download the Linux kernel source code
The official source for obtaining the kernel code is kernel.orgFrom there you can choose between mainline, stable, and long-term support (LTS) versions. Each has its own folder and a link to a tarball compressed.
Some examples of downloads that are often seen The tutorials are:
- Stable kernel 6.6 for recent testing:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz - Kernel 6.0.11 (v6.x branch):
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.0.11.tar.xz - Kernel 5.10.13 (v5.x branch):
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.13.tar.xz
You can also download the fonts from the repositories of your distributionIn Debian/Ubuntu, for example, there is the package linux-source:
sudo apt-get install linux-source
This leaves a file of type linux-source-xxxtar.bz2 en / usr / srcwhich you can decompress in a similar way to the kernel.org tarball.
Prepare the source tree and disk space
Once you have downloaded the kernel tarball, you need to extract it to a location where you have sufficient space and writing permissionsYou're not obligated to use /usr/src, although it's a classic. You can create, for example, a directory like ~/Downloads/my-kernels.
Keep in mind that, when uncompressed, the source tree may be around 1,5 GBand during compilation, things easily jump above the 7 GBSo leave plenty of room for error.
typical examples of decompression are:
- With tar.xz:
tar avxf linux-6.6.tar.xz - With tar.bz2:
tar jxvf linux-2.6.36.tar.bz2 -C /usr/src - With tar.gz:
tar zxvf linux-x.x.x.x.tar.gz -C /usr/src
After unzipping, you will have a directory like linux-6.6 o linux-5.10.13You can create a generic symbolic link called linux to avoid going crazy with the routes:
cd /usr/src
sudo ln -s linux-6.0.11 linux
It is not mandatory to place the sources in / usr / src, although many guides do it out of tradition. The compilation and installation will work the same if you do it in your user folder.provided you have the space and appropriate permits.
Reuse the current kernel configuration
Configuring a kernel from scratch, option by option, is an endless task even for very experienced people. The usual practice is reuse the kernel configuration you are already using as starting point.
To do this, it is first necessary to know which kernel do you have loaded? at this time:
uname -r
The result will be something like 6.1.0-13-amd64 o 4.19.0-6-amd64With that information, you can copy the current configuration from / Boot to the directory of the newly decompressed sources:
cd linux-6.6
cp /boot/config-$(uname -r) .config
That file .config This will be the one the kernel build system uses as a base. In newer versions, when running the configuration tools, you will only be asked for options that did not exist in your previous kernelwhich saves a huge amount of time.
How to adjust the settings to the actual hardware
In addition to reusing the current .config file, you can fine-tune it even further using the tools provided by the kernel tree itself. One particularly useful tool is make localmodconfig, which attempts to generate a configuration adapted to the modules you have loaded at that moment.
Within the source directory, simply run:
make localmodconfig
This command inspects the active modules and It disables many things that your system isn't using.This is ideal if you're configuring a kernel for that specific machine. If you intend to compile a generic kernel for other machines or servers, you'll need to carefully review it afterward to ensure you don't leave out hardware that isn't present on the system where you're compiling.
Kernel configuration modes: text and graphical environments
Kernel configuration can be done in several ways. All of them end up generating or modifying the file .configBut the experience is very different depending on the mode:
- make configA purely text-based questionnaire, question by question. Today it is considered practical only for very specific cases; it is slow, tedious, and easy to make mistakes.
- make menuconfigText-based menu interface (ncurses), very common on servers or when you don't have a graphical environment. You navigate with arrow keys, tab, and spacebar.
- make xconfigA Qt-based graphical interface, comfortable for mouse use. Ideal when working from a full desktop.
- make gconfig: GTK-based graphical interface, designed for GNOME-type environments.
In practice, make menuconfig It's the star in almost every guide because it works in almost any context. Starting with your copied .config file, all you need to do is:
make menuconfig
You'll see a main menu with categories like "Processor type and features," "Device Drivers," "File systems," "Networking support," "Virtualization," etc. Within each one, you'll be able to activate, deactivate or mark as module The different options. Normally:
- [*] It means "built-in".
- [M] It indicates "it is compiled as a loadable module."
- [] It is "deactivated".
The idea is to integrate into the kernel what is necessary to boot the system (for example, root disk support), and use modules for less critical features or features that are not always usedso that the main kernel is lighter.
Each menu item usually has an option to Help This explains exactly what it does and sometimes provides a default recommendation. If you're unsure about something very specific, it's best to stick with the recommended value or the one that was already enabled in the previous configuration.
Useful settings: file systems, virtualization, and Docker
An important part of kernel customization is choosing well What file systems, container mechanisms, and network options? You'll need it. For example, if you plan to use partitions NTFS With writing, you will need to activate the corresponding support (usually located in "File systems → DOS/FAT/EXFAT/NT Filesystems").
If you plan to work with virtualization or containers, there are blocks of options that are vital to review. For Docker and Docker Swarm, for example, there are a number of functions of namespaces, cgroups and network that must be active:
- cgroup hierarchy.
CONFIG_NAMESPACES,CONFIG_NET_NS,CONFIG_PID_NS,CONFIG_IPC_NS,CONFIG_UTS_NS.CONFIG_CGROUPSand sub-options such asCONFIG_CGROUP_CPUACCT,CONFIG_CGROUP_DEVICE,CONFIG_CGROUP_FREEZER,CONFIG_CGROUP_SCHED,CONFIG_CPUSETS,CONFIG_MEMCG.- Key support (
CONFIG_KEYS). - Network options such as
CONFIG_VETH,CONFIG_BRIDGE,CONFIG_BRIDGE_NETFILTER,CONFIG_NF_NAT_IPV4,CONFIG_IP_NF_FILTER,CONFIG_IP_NF_TARGET_MASQUERADE,CONFIG_NETFILTER_XT_MATCH_ADDRTYPE,CONFIG_NETFILTER_XT_MATCH_CONNTRACK,CONFIG_NETFILTER_XT_MATCH_IPVS,CONFIG_IP_NF_NAT,CONFIG_NF_NAT,CONFIG_NF_NAT_NEEDED. - POSIX queue support (
CONFIG_POSIX_MQUEUE). - Options like
CONFIG_IPVLANfor certain network configurations used by Docker.
Much of this functionality can be compiled as a module without issue, but It's advisable to review the Docker documentation or use testing scriptsThere are utilities such as check-config.sh that analyze the kernel's .config file and tell you what's missing for full container compatibility.
The basic mechanics would be:
chmod +x check-config.sh
./check-config.sh .config
The output will show you which options are OK, which are missing, or which are misconfigured. If you find anything critical disabled, you can run it again. make menuconfig o make xconfig, correct it, save and repeat the verification.
Interesting improvements in recent kernel versions
In addition to customization, many people compile new versions of the kernel to Take advantage of performance improvements and new features which will still take some time to reach the packages of your distribution.
For example, in the Frame 6.6 Improvements have been mentioned such as:
- Notable performance increase in EXT4, with increases of up to 34% in certain concurrent write loads.
- Improvements in GPU support NVIDIA using the free driver New, preparing the ground for the NVK (Vulkan) driver.
- Options for configure aspects of the BIOS from HP equipment directly from Linux.
- Cluster scheduling settings for hybrid processors Intel (Alder Lake, Raptor Lake and later).
- Optimization of direct asynchronous I/O with io_uring, with performance increases of around 37% in certain tests.
- A new task planner, EEVDF (Earliest Eligible Virtual Deadline First), which improves CPU allocation between processes.
All of this comes "out of the box" in modern versions, but your distribution may take time to package or enable it, which is why many people resort to manually compile a newer kernel.
Compiling the kernel: make, modules, and compilation threads
Once you have the configuration the way you want it, it's time to put the CPU to work. This is where the commands come in. make Classic kernel compilation. Compilation can take anywhere from several minutes to over an hour, depending on the hardware and how many modules you're generating.
In essence, the basic flow In Debian/Ubuntu (or other distros) it is usually:
- Compile the kernel (main image):
make -j$(nproc)
Or, if you want it to use only one core:
make - Compile and install the modules:
sudo make modules_install
The option -j$(nproc) It tells make to use as many parallel processes as your CPU has cores, which saves a lot of time on modern machines. If you see errors during compilation, you'll need to check them at the point where they fail; they could be due to missing dependencies, conflicting configurations, or specific bugs in that kernel version.
Some more advanced recipes use the Debian tool make-kpkg and the package kernel-package to package the kernel into .deb files. This then allows you to install and uninstall the custom kernel as if it were just another package, with something like:
fakeroot make-kpkg --initrd --append-to-version=-custom kernel_image kernel_headers
cd /usr/src
sudo dpkg -i *.deb
In that scenario, it is also common to encounter errors related to kernel certificatesMany guides solve specific problems by disabling trusted keys in the .config file with a line like this:
sed -i '/CONFIG_SYSTEM_TRUSTED_KEYS/s/^/#/g' .config
Install the newly compiled kernel and update the bootloader
If you're not using .deb packaging and are going "bareback" with the standard kernel tree tools, the Installation is done directly from the source directoryThe most common sequence after compilation is:
- Install the modules (if you haven't already):
sudo make modules_install - Install the kernel:
sudo make install
The kernel's own scripting system will copy the binary bzImage generated to /boot, along with System.map and the configuration file. In Debian/Ubuntu, scripts are typically triggered in /etc/kernel/postinst.d that generate the initramfs and update the boot manager (GRUB) automatically.
Even so, it never hurts to explicitly execute:
sudo update-initramfs -u
sudo update-grub
sudo update-grub2
With this You make sure that the initial boot image has been regenerated correctly. for the new kernel version, and that GRUB takes it into account in its menu. In other distributions, such as some based on Red Hat, it can be used mkinitrd o dracut instead of update-initramfs, but the goal is the same: create an initrd/initramfs image suitable for the new kernel.
The role of initrd/initramfs and potential problems
The initrd or initramfs is a file system image that is loaded into memory very early in the boot processIt contains the minimum drivers necessary to mount the actual root file system (for example, support for the SATA or NVMe controller where your / partition is located).
If your initrd is incorrectly generated or does not contain the necessary modules, the kernel will boot but will not be able to mount / and you'll end up with a kernel panic complaining that he can't find the root filesystem. This is a typical error when critical kernel options are disabled or the initramfs is forgotten after changing versions.
In Debian/Ubuntu, the reference command today is update-initramfs:
sudo update-initramfs -c -k x.x.x
Parameter -c creates a new image, and -k indicates the exact kernel version. In older distributions (or with different tools) it was used mkinitrd with similar syntax:
cd /boot
mkinitrd -o initrd.img-2.6.36 2.6.36
In any case, if after installing your custom kernel you see errors related to /lib/modules or to mounting the root, First, check initramfs/initrd and the GRUB configuration. before touching anything else.
Verify that the new kernel is working correctly
With everything installed and the boot manager updated, it's time to reboot to test the system. During startup, monitor GRUB and kernel boot messages in case errors appear from modules, file systems or devices that are not recognized.
Once inside the system, you can check which kernel version you are using with:
uname -a
The output should reflect the newly compiled versionFrom there, it's a matter of testing your usual services: web server, databases, Docker, Virtual machinesdesktop programs, etc. If everything is working correctly, you can leave that kernel as the main one and keep older versions as backups.
How to revert to a previous kernel and uninstall the new one
If something goes wrong (which can happen, especially the first few times), the important thing is that Don't panicAs long as your GRUB lists other working kernels, you can recover the system without too much trouble.
The process typical would:
- Restart the system.
- On the GRUB screen, move with the arrows and enter the type section "Advanced options for…".
- Choose an older kernel version that you know worked well.
- Boot with that kernel and, once inside, proceed to delete the problematic kernel.
If you installed the kernel manually, without .deb packages, removal usually involves delete the corresponding files in /boot and /lib/modulesFor example, to remove a 6.6.0 you could do:
cd /boot
sudo rm config-6.6.0 initrd.img-6.6.0 System.map-6.6.0 vmlinuz-6.6.0
And then, delete its modules:
cd /lib/modules
sudo rm -rf 6.6.0
When finished, update GRUB so that it no longer offers that kernel in the menu and reboot:
sudo update-grub
sudo update-grub2
sudo reboot
If you installed the kernel packaged as .deb, it's cleaner. Use it like any other package Use apt or dpkg to uninstall it, keeping the system state better under control.
Notes for other distributions: Fedora, CentOS and others
Although this guide focuses heavily on Debian/Ubuntu/Mint, the general logic is similar in Red Hat-based distributions like Fedora or CentOS. What changes are package management tools, some dependency names, and how to access the boot manager.
In Fedora/CentOS, for example, a basic workflow for compiling a kernel from kernel.org might be:
- Install the development tools:
su -c 'yum groupinstall "Development Tools"'
su -c 'yum install ncurses-devel qt-devel unifdef' - Download a stable version (such as 2.6.36 in the classic examples):
cd /tmp
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.36.tar.bz2 - Unzip and prepare the source tree:
mkdir /usr/src/linux
tar -xjvf linux-2.6.36.tar.bz2 -C /usr/src/linux
cd /usr/src/linux - Configure the kernel using menuconfig, xconfig, or gconfig.
- Compile and install:
make
make modules
make modules_install
make install
Then you will have to review and edit /boot/grub/grub.conf (or the equivalent file, depending on whether you use GRUB Legacy, GRUB2, etc.) to add an entry for the new kernel with its corresponding initrd, taking great care with the paths of root = and references to logical volumes if you use LVM.
Compiling, configuring, and installing a custom Linux kernel is a lengthy but incredibly instructive process: it forces you to understand which modules you need to boot, which options are essential for your services (like Docker or virtualization), how initramfs and GRUB are integrated into the boot process, and how to always maintain a fallback option to revert to a previous kernel if something goes wrong. If you take the time to review each section, intelligently reuse your current kernel configuration, and get used to testing changes gradually, you can end up enjoying a truly powerful system. more optimized, tailored to your hardware and aligned with your real needs than that provided by the generic kernels of most distributions.
Passionate writer about the world of bytes and technology in general. I love sharing my knowledge through writing, and that's what I'll do on this blog, show you all the most interesting things about gadgets, software, hardware, tech trends, and more. My goal is to help you navigate the digital world in a simple and entertaining way.
