Obtaining, configuring, compiling, packaging and installing a new kernel in Ubuntu, can be a daunting task. I chose Ubuntu for this guide, as this guide can also be used in other "debian" based distro's, like debian, Linux mint, and any ubuntu variants. "The Debian Way", how and why things are done on a debian based distro, was adopted by Ubuntu as well, and Debian has a unique way of handling building new kernels for your installation.

Step One: Preparing your system.

Open up a terminal. Enter the following command:

In Terminal Commands:
export CHOST="x86_64-pc-Linux-gnu"
export CFLAGS="-march=native -O2 -pipe"

I will explain these:

CONCURRENCY_LEVEL, for some programs, mainly the program we will be using to build the kernel the "debian" way, it is capable of using multiple cores, with this variable set to the number of cores of your CPU, it will use all of them when compiling the kernel.

CHOST, this variable is for gcc, the compiler used in Linux. This line tells gcc what architecture to build for. this is currently set for Intel/AMD x86_64 cpu's and 64 bit distro's, if you are building for a 32 bit distro, use CHOST="i686-pc-Linux-gnu", instead. This flag isn't always needed, you can exclude it if you want.

CFLAGS, these are compile flags, mainly for optimization for the binary. -march, the family of your CPU, latest versions of GCC can auto detect these features, setting it to native is suitable in most cases. Setting -march allows GCC to compile the code to take advantage of any feature of your CPU. -O2 and -pipe, are another optimization flag. There are more flags, but these are "generic" ones used, that offer a decent amount of benefits, I'm afraid going into more detail, is beyond the scope of this guide.

CXXFLAGS, extra flags for GCC, typically you can set them to CFLAGS, which has be done here.

Keep the terminal open, as everything you will be doing will require it. (if you close the terminal, you will need to export those variables again.)

In Terminal Commands:
sudo apt-get update

This command will sync apt to Ubuntu's repositories, giving you access to the latest available software.

In Terminal Commands:
sudo apt-get install build-essential kernel-package libncurses5-dev fakeroot wget bzip2

This command will download and install all the needed tools and programs you will need to accomplish the task of building a kernel (among other software). Do not worry if some of these items are already installed, apt is smart enough to exclude them from a reinstall, and only install what is missing.

Step Two: Setting up the build environment and getting the kernel source.

We will need to setup a directory from which to extract the source, and work on it from there. So lets create a directory to work from and enter it.

In Terminal Commands:
mkdir ~/kernel-build
cd ~/kernel-build

This has created a new directory in your home directory named, kernel-build, this is where we extract the kernel source and build the kernel from. Now we will need to choose, I would suggest getting the "stable" branch kernel, or sticking with the kernel version you already have, to find out what kernel version your Ubuntu is running, do the following:

In Terminal Command:
uname -r

This will produce something like this: 3.0.0-11-generic, the first 3 decimal places will be the kernel version your, the other numbers is build information for Ubuntu patches and revisions. Now there are a few ways to get the kernel source, you can go to kernel.org, from apt-get, or GIT. I will only cover how to get the source from kernel.org and apt-get, as GIT would require a bit more injection into this guide than is needed.


In Terminal command:
apt-get source linux-image-$(uname -r)

This command will download and extract the kernel source without any further interaction from you.

Other Way:

This way involves going to kernel.org, and browsing their FTP and downloading the kernel, then extracting it it to your build folder. I will provide the latest stable kernel version here (and will try to keep this link up to date as well.)

In Terminal Command:
wget http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.1.1.tar.bz2
tar -xjf linux-3.1.1.tar.bz2

This will download and then extract the kernel source into your build folder.

Step Three: The Fun...Configuring and Building the kernel source.

Enter the kernel source directory:

In Terminal Command:
cd Linux-*

I typically use the existing configuration of the running kernel as a basis, you can skip this step if you want to start from scratch or you use one from another kernel.

In Terminal Command:
cp /boot/config-`uname -r` ./.config

This will copy over the current configuration file to the kernel source.

In Terminal Command:
make oldconfig

This command can produce a bunch of questions, on how you want to handle the new modules or even new features of new kernels, answer the best of your ability. Once that is done, we can now configure the kernel.

In Terminal Command:
make menuconfig

This will bring up a ncurse interface that allows you to load a configuration file, and to configure the kernel (there are other front ends to configuring a kernel, but they require additional libs to be installed, if you wish to use them instead, be my guest). First thing you want to do, just in case it didn't load, is to load the copied .config file.

Load an Alternate configuration File

locate the .config file, and load it.

Once it is loaded, you will be presented with a bunch of sections, that control different aspects of the kernel configuration. At this stage, you should know what you are doing, or be willing to learn. Enter into each section, use the arrow keys to navigate up and down, and use the space bar to "activate" or to "deactivate" options, when a option is activate an * will appear, deactivate, it will be blank. when you get to the driver section, modules/drivers can be built into the kernel which will be *, built as a module a M,and not built will be blank.

If you do not know what something is, hit H, it will bring up a "help" page over it, advising you what it is, and sometimes advice if you want it enabled or not. Some times this help is not very "helpful", so you can ask in the forum here or use the almighty google. Take your time in this process, as the kernel is the heart of your distro, you want it to be the best it can be. Once you have finished here save the configuration and exit menuconfig.

NOTE: I typically build all drivers as modules, even the ones I don't use, it makes the kernel a little more portable, and I don't have to worry about future upgrades or adding additional hardware.

After you have configured the kernel, you can now build it.

In Terminal Command:
fakeroot make-kpkg --initrd --append-to-version=-customname kernel_image kernel_headers

Find the line, --append-to-version=-customname, change this to what you want, restrict the name scheme to alpha/numeric and lowercase, this will give your kernel a "custom" name. Once you have done this, run the command, it will take awhile depending on concurrency that you set and how fast your CPU is. Once this process is done, In the parent directory of your build directory, two new files will appear, one will be the kernel-image.deb and the other will be kernel-headers.deb, they will be named similar to this:



They will be the only two .deb files in the build directory, you can install like this:

In Terminal Commands:
cd ..
sudo dpkg -i Linux-image-*.deb
sudo dpkg -i Linux-headers-*.deb
sudo update-grub

Congratulations, if all worked out as planned, you have a new customized kernel. Restart, and select the kernel you want to boot into (if Ubuntu is the only OS installed, the grub selection menu will not show up by default, but it will default to load the latest kernel, if you wish to get to the grub splash screen, hold down the shift key after POST is done). After you are done, you should keep the .deb files, but you can go ahead and remove the build directory.

Step Four: Why would I want to do this?

Well Ubuntu ships with what they call a Generic kernel. which is bloated with all sorts of options, kernel drivers, and patches you might not need. or it doesn't include something you want it to include. There are a lot of reasons why one would want to compile their own custom kernel.

One of the biggest benefits to a custom kernel, is the optimization you can make to it to match your CPU and your system. It could improve performance of your ubuntu install greatly.

The other reason, you might have a non-standard configuration of hardware, that you need ubuntu to use correctly and the only way to do that is to setup a customized kernel.

And the Greatest reason behind doing this, the knowledge you can walk away with, how often have you been given a chance to see on the most basic level, how a computer runs, and then make the decisions that can effect the way it does