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


yum install ncurses-devel
yum groupinstall "Development Tools"

Obtain the kernel source code

The kernel source can be obtained from . linux-3.0.8 was the highest stable version available at the time of this writing.


Extract the source

tar xvf linux-3.0.8.tar.bz2
cd ~/src/linux-3.0.8

Apply any needed patches

In this example I will use fbcondecor as it is a small, but fun patch that adds decoration to you console.

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 < fbcondecor-0.9.6-3.0-rc2.patch

Assuming there are no errors, apply the patch:

patch -p1 < fbcondecor-0.9.6-3.0-rc2.patch

patching file Documentation/fb/00-INDEX
patching file Documentation/fb/fbcondecor.txt
patching file drivers/Makefile
patching file drivers/video/Kconfig
patching file drivers/video/console/Kconfig
patching file drivers/video/console/Makefile
patching file drivers/video/console/bitblit.c
patching file drivers/video/console/cfbcondecor.c
patching file drivers/video/console/fbcon.c
patching file drivers/video/console/fbcondecor.c
patching file drivers/video/console/fbcondecor.h
patching file drivers/video/fbcmap.c
patching file drivers/video/fbmem.c
patching file include/linux/console_decor.h
patching file include/linux/console_struct.h
patching file include/linux/fb.h
patching file kernel/sysctl.c

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 oldconfig . Once you are comfortable with the configuration options move to make localmodconfig .

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

The config option is a command line tool and will ask, in order, each and every option, do not use this tool.

Easy configuration

The easy way to start with a custom kernel is to 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- ~/src/linux-3.0.8/.config
make oldconfig
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 oldconfig or localmodconfig .

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 this link for a discussion on kernel modules.

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 feel ready to build a more custom kernel, use localmodconfig . This will use lsmod to examine what modules are currently in use, and then configure 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

If you get an error:

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

copy your configuration file from /boot

cp /boot/config- ~/src/linux-3.0.8/.config
make localmodconfig
make menuconfig

localyesconfig is similar, but builds the drivers into the kernel. The result is a larger kernel that will boot faster.

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.

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.

sudo make modules_install

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-3.0.8

Copy the config and

sudo cp /boot/
sudo cp .config /boot/config-3.0.8

Make an initramfs


sudo update-initramfs -c -k 3.0.8


sudo dracut /boot/initramfs-3.0.8.img 3.0.8

configure your boot loader

Fedora 16 is now using grub2 so it is trivial to update your boot menu.

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