Reasons to compile a custom kernel:

Reasons NOT to compile a custom kernel:

Compile as root or as a user:

Although you may compile the kernel either as root or as a user, you will need root access to install the kernel, install the kernel modules, and configure the boot loader.

When compiling as root, most tutorials will use /usr/src/linux as a working directory. The source code is extracted into /usr/src/linux-x.y.x (x.y.z = kernel version #) and a link is made from /usr/src/linux-x.y.x to /usr/src/linux .

When compiling as a user, use a location in your home directory. I personally use ~/src

Vanilla kernel

A "Vanilla" or stable kernel is obtained from The Linux Kernel Archives .

Kernel development follows a time-based process with new features / patches added during the release cycle.

At the beginning of each release cycle, the features and patches deemed stable enough for inclusion are merged into the mainline kernel.

The next kernel is the set of patches submitted for consideration for inclusion the "next" release cycle.

For a more detailed discussion of the kernel development cycle and terminology see : - How the development process works

Distribution kernels

Many distributions, Fedora and Ubuntu included, provide a modified kernel with patches or customized configurations, selinux and apparmor for example. In addition, scripts are provided to automate kernel compilation including configuration, packaging (.deb or .rpm), installation, and updating grub. While these scripts automate the process, they are going to by definition be somewhat distribution centric.

Ubuntu offers several optimized kernels called Ubuntu kernel flavors. Common flavors are generic, pae, server, virtual, xen-dom0 and you may examine the .config file for additional details.

For distribution specific guides see:

Other kernels

In addition pre-compiled kernels are supplied by other third parties. For example, the zen kernel AKA liquorix on Debian/Ubuntu is optimized for desktops and multimedia. The zen (liquorix) includes code (patches) outside the mainline kernel and uses configuration options to gain performance at the potential expense of stability.

Building a vanilla kernel

Learning to compile a Vanilla kernel is a great first, and will help you to understand some of the automated tool sets used by some distros.

In this tutorial I will be compiling as a user using ~/src as a working directory.

mkdir ~/src
cd ~/src

Install the development tools needed to compile

Debian / Ubuntu:

sudo apt-get install build-essential libncurses5-dev libssl-dev


dnf install ncurses-devel openssl-devel
dnf group install "Development Tools"

Obtain the kernel source code

The kernel source can be obtained from . linux-4.11.6 was the most recent stable release available at the time of this update.


Extract the source

tar xvf linux-4.11.6.tar.xz
cd ~/src/linux-4.11.6

Apply any needed patches

In this example I will use fbcondecor patches as it is a small, but fun patch that adds decoration to you console. Additional information on fbcondecor can be found on This gentoo page

fbcondecor screen shot

Note: fbcondecor requires additional configuration beyond patching and compiling the kernel. See the links below for distribution specific advice (I have only done this in gentoo, not sure if it works for ubuntu).

cd ~/src/linux-3.0.8

Test the patch:

patch --dry-run -p1 < 4200_fbcondecor.patch

Assuming there are no errors, apply the patch:

Note: fbcondecor is long in the tooth and there have been no comitts since 2012. With kernel 4.x I get messages about missing files in the kernel source, but the patches apply without problems except the missing source files.

Note: fbcondecor is long in the tooth and it is difficult to find themes. You can search the gentoo packages, but

patch -p1 < 4200_fbcondecor.patch

patch --dry-run -p1 > 4200_fbcondecor.patch
checking file Documentation/fb/00-INDEX
checking file Documentation/fb/fbcondecor.txt
checking file drivers/Makefile
Hunk #1 succeeded at 20 with fuzz 1 (offset 3 lines).
Hunk #2 succeeded at 54 (offset 5 lines).
checking file drivers/video/console/Kconfig
Hunk #1 succeeded at 151 (offset 21 lines).
checking file drivers/video/console/Makefile
checking file drivers/video/console/bitblit.c
checking file drivers/video/console/cfbcondecor.c
checking file drivers/video/console/fbcon.c
Hunk #3 succeeded at 281 (offset -2 lines).
Hunk #4 succeeded at 543 (offset -4 lines).
Hunk #5 succeeded at 1005 (offset -4 lines).
Hunk #6 succeeded at 1040 (offset -4 lines).
Hunk #7 succeeded at 1270 (offset 1 line).
Hunk #8 succeeded at 1294 (offset 1 line).
Hunk #9 succeeded at 1318 (offset 1 line).
Hunk #10 succeeded at 1844 (offset 1 line).
Hunk #11 succeeded at 1937 (offset 1 line).
Hunk #12 succeeded at 2087 (offset 1 line).
Hunk #13 succeeded at 2164 (offset 1 line).
Hunk #14 succeeded at 2201 (offset 1 line).
Hunk #15 succeeded at 2235 (offset 1 line).
Hunk #16 succeeded at 2278 (offset 1 line).
Hunk #17 succeeded at 2398 (offset 1 line).
Hunk #18 succeeded at 2594 with fuzz 1 (offset 9 lines).
Hunk #19 succeeded at 2738 (offset 9 lines).
Hunk #20 succeeded at 2768 (offset 9 lines).
Hunk #21 succeeded at 3033 (offset 9 lines).
Hunk #22 succeeded at 3085 (offset 9 lines).
Hunk #23 succeeded at 3727 (offset 9 lines).
checking file drivers/video/console/fbcondecor.c
checking file drivers/video/console/fbcondecor.h
checking file drivers/video/fbdev/Kconfig
Hunk #1 succeeded at 1228 (offset 12 lines).
checking file drivers/video/fbdev/core/fbcmap.c
Hunk #2 succeeded at 258 (offset 2 lines).
checking file drivers/video/fbdev/core/fbmem.c
checking file include/linux/console_decor.h
checking file include/linux/console_struct.h
checking file include/linux/fb.h
checking file include/uapi/linux/fb.h
checking file kernel/sysctl.c
Hunk #1 succeeded at 150 (offset 1 line).
Hunk #2 succeeded at 266 (offset -4 lines).

Kernel configuration

Kernel configuration is where the rubber hits the pavement. One of the most common mistakes made when learning to compile a kernel is to try to write a configuration file from scratch. The result is either you compile a kernel without sufficient drivers to run on your hardware or rapidly become overwhelmed with the options.

The configuration file is called ".config" and is written by make using one of the configuration options. Common options are:

  config          - Update current config utilising a line-oriented program
  menuconfig      - Update current config utilising a menu based program
  xconfig         - Update current config utilising a QT based front-end
  gconfig         - Update current config utilising a GTK based front-end
  oldconfig       - Update current config utilising a provided .config as base
  localmodconfig  - Update current config disabling modules not loaded
  localyesconfig  - Update current config converting local mods to core
  silentoldconfig - Same as oldconfig, but quietly, additionally update deps
  defconfig       - New config with default from ARCH supplied defconfig

If you are building a kernel for the fist time, I highly suggest you start with make localmodconfig as this will detect and compile the modules (drivers) your system is currently using and write a .config file. Once you are comfortable with the configuration options move to make oldconfig or other options.

The config option is a command line tool and will ask, in order, each and every option, I do not advise using this method to write a .config file.


The option localmodconfig will use lsmod to examine what modules are currently in use, and then write your .config to build only those modules. The result is a shorter compilation time and a kernel and modules specific to your hardware.

localmodconfig must be run from a working 'generic' kernel with the drivers for your hardware loaded as modules. Otherwise, lsmod will not identify drivers built into the kernel, and localmodconfig will not work as expected.

After running localmodconfig , review the configuration with make menuconfig


The localyesconfig option is similar to localmodconfg, but builds the drivers into the kernel rather then as modules. The result is a larger kernel that will boot faster.

Configuration using an oldconfig option

This option generates a configuration file use an old, working configuration file from any distribution. A copy of the configuration file is saved for you in /boot. Simply copy the configuration, use make oldconfig to generate a .config file using the old as a template. You will be asked to answer any questions regarding new features and are safe using the defaults (hit the enter key). It is the prudent to review the configuration changes with make menuconfig .

cp /boot/config-4.11.5-200.fc25.x86_64 ~/src/linux-4.11.6/.config

make oldconfig

After running oldconfig , review the configuration with make menuconfig


menuconfig is a command line, ncurses, menu driven interface used to configure your kernel options. I typically use menuconfig to review and fine tune my configuration after using other tools such as localmodconfig or oldconfig .

make menuconfig

First configuration

You can obtain additional information at any time using the "h" hotkey.

Configuration help

Use the arrow keys to navigate up and down through the menu options. Items marked with a ---> are sub menus, use the enter key to enter into the sub menu.

To configure a driver, use "n" to remove a driver, "y" to compile the driver into the kernel, and "m" to compile it as a module. The modules you are currently using can be listed with lsmod

The linux kernel is modular and modules (drivers)can be loaded as needed. In fact, if you examine the configuration file from most distros you will see, rather than building a large kernel image, many drivers are loaded as modules.

See Modifying the Kernel to Improve Performance for a discussion on optimizing kernel performance.

Graphical tools

xconfig and gconfig are graphical tools to configure your kernel. To use them you will need to install some dependencies.

Ubuntu / Debian

    menuconfig: libncurses5-dev
    xconfig: libqt3-mt-dev
    gconfig: libgtk2.0-dev libglib2.0-dev libglade2-dev


    menuconfig: ncurses-devel
    xconfig: qt3-devel libXi-devel
    gconfig: gtk2-devel libglade2-devel

If you get an error:

No config file found at scripts/kconfig/ line 110.
make[1]: *** [localmodconfig] Error 2
make: *** [localmodconfig] Error 2

you need to first write a configuartion file using localmodconfig or oldconfig

Kernel configuration from scratch using a kernel seed

For a minimal, default configuration see kernel seeds. If you want to learn kernel configuration in detail, this site has a wealth of additional information and the kernel seeds are a great start. BE WARNED - These seeds are minimal and you will almost certainly need to know your hardware in order to add in drivers.

The "problem" with using the above method is that the kernel seed is indeed a minimal configuration and anticipate the need to identify your hardware and enable additional drivers.

Use lspci -v to identify your hardware and kernel drivers required.

lspci -v

00:04.0 Audio device: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (rev 01)
        Subsystem: Red Hat, Inc Device 1100
        Flags: bus master, fast devsel, latency 0, IRQ 11
        Memory at f8040000 (32-bit, non-prefetchable) [size=16K]
        Capabilities: [50] MSI- Enable- Count=1/1 Maskable- 64bit+
        Kernel driver in use: HDA Intel

00:01.2 USB Controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II[ (rev 01) (prog-if 00 [UHCI])
        Subsystem: Red Hat, Inc Qemu virtual machine
        Flags: bus master, fast devsel, latency 0, IRQ 11
        I/O ports at c020 [size=32]
        Kernel driver in use: uhci_hcd

From the above output we can determine we need to compile a kernel with the HAD Intel and uhci_hcd drivers. To find and enable them, run make menuconfig and enable the driver or if you can not locate them use the search function. To search for a driver option, hit the "/" key and enter your search parameters in the box. If all else fails, use google.

Use one of the methods listed below and then proceed to Compile section.

Select configuration options

This section is optional and is for advice on enabling specific drivers. The information will be helpful to those using a kernel seed .


As of kernel 3.1.4, support for the GMA500 is in the staging drivers. The option may he hidden or may not be obvious.

To compile the driver, DRM_PSB, you have to enable the following options in the Device Drivers section :

  1. Graphics Support -> Direct Rendering Manager
  2. Staging Drivers -> Intel GMA5/600 KMS Framebuffer

GMA 500


The fbcondecor option will be hidden unless you disable Tile Blitting Support.

Navigate to:
Device Drivers ->
Graphics support ->
Support for frame buffer devices ->

Disable (hit "n" )'Enable Tile Blitting Support'

Enable fbcondecor
Navigate to:
Device Drivers ->
Graphics Support ->
Console Display Driver Support ->

Support for Framebuffer Console Decorations #hit "y"


Device Drivers --->
 Multiple devices driver support (RAID and LVM) --->
  [*] Multiple devices driver support (RAID and LVM)
  < >   RAID support
  <M>   Device mapper support

KVM optimization

KVM Guests see KVM Kernel Tuning .

The spice vdagent needs the kernel configuration option INPUT_UINPUT

I do have some .config you can use as a seed for KVM guests including server with selinux and server without selinux and desktop with selinux.


Selinux is a part of the mainline kernel and thus no patch is required.

See the gentoo selinux page for a concise overview of the kernel configuration options.



grsecurity is a kernel patch to increase security and is used in the gentoo-hardened kernel.

See the gentoo grsecurity page for a concise overview of kernel configuration options.


To enable Ecryptfs see Ecryptfs FAQ .


Compiling the kernel is the easy part, but may take some time depending on the speed of your processor. You can speed up the process by running multiple jobs. Typically the number of jobs is specified with the -j option and is = the number of CPU + 1

make -j5

Recite the ancient incantations

Then compile the modules

make -j5 modules

Recompile a kernel

Somewhere in the course of compiling kernels you will inevitably need a re-do. You have a few options to make things faster.

First, if you simply need to compile a module, edit your .config file and run make modules && sudo make modules_install .

If you are compiling new options into the kernel itself, simply re-run make make -j5

If you want a fresh start, run make clean


Installation requires root access. You may use su or sudo, I will use sudo to indicate root access is required.

Copy the new kernel to boot (arch/x86_64/boot/bzImage is a link to arch/x86/boot/bzImage so the following command works on both 32 AND 64 bit arch.)

sudo cp arch/x86/boot/bzImage /boot/vmlinuz-4.11.6

Copy the config and

sudo cp /boot/ /boot/
sudo cp .config /boot/config-4.11.6

Module installation

By default the modules will be built with debug information resulting in a huge /lib/modules/3.x.x directory, as much as 2 Gb or larger.

To reduce the size of your installed modules, set the INSTALL_MOD_STRIP environment variable to 1 when installing the modules

sudo INSTALL_MOD_STRIP=1 make modules_install

Make an initramfs


sudo update-initramfs -c -k 4.11.6


sudo dracut /boot/initramfs-4.11.6.img 4.11.6

configure your boot loader

For Fedora the grub menu is updated using grub2-mkconfig.

#Non EFI
grub2-mkconfig -o /boot/grub2/grub.cfg

#EFI systems
grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg

sudo update-grub


Finally, time to boot into your new kernel. If all goes well you will have a nice new toy.


The most common reason a kernel will not boot is a missing driver. Boot an older, working kernel and review the modules and drivers in use and check to see the appropriate drives are compiled.

lsmod lspci -v

google search any driver listed in lspci you are unfamiliar with.

You can also try using make localmodconfig

make localmodconfig
make menuconfig

If all else fails, fall back to make oldconfig

cp /boot/config-x.y.z . #copy a working config file from /boot
make oldconfig


I built a custom kernel on Fedora 15 optimized to be used in a KVM guest with selinux enabled.

Default kernel
size = 3.8M
free -m
                     total       used        free
Mem:             999        446        552
-/+ buffers/cache:         283        715

Startup finished in 991ms (kernel) + 2604ms (initrd) + 13815ms (userspace) = 17411ms

custom (virtual) kernel
size = 2.9 M
free -m
                     total       used        free
Mem:             998        309        689
-/+ buffers/cache:         157        841

Startup finished in 5636ms (kernel) + 2507ms (initrd) + 9431ms (userspace) = 17575ms