Thanks to Jesse Goerz for taking the biggest step and writing the first three versions of this document, and for graciously allowing me to carry it forward.

This document is intended to help Debian newbies use the kernel-package system to create custom kernels. Copyright © 2003 Kevin McKinley, NewbieDoc project . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license can be found at the Free Software Foundation .

Please remember that inevitably, some people will use this document and screw up their systems. Don't be one of them. If you don't understand something, get more information before proceeding. If you see something here that you know is a mistake, please let me know at < newbiedoc-discuss@lists.sourceforge.net > .

You can make your system unbootable if you're not careful. I highly recommend you read this entire document at least once, then work through it as you build your kernel.

If you have ever compiled a kernel you will be amazed at how easy it can be. This tutorial was designed to enable you to use Debian's kernel-package system, which simplifies building and installing custom kernels. Learn to create Debian packages of kernels and their modules, and manage the resulting kernel images with dpkg.

I used to compile kernels manually, and it involved a series of steps to be taken in order; kernel-package was written to take all the required steps (it has grown beyond that now, but essentially, that is what it does). This is especially important to novices: make-kpkg takes all the steps required to compile a kernel, and installation of kernels is a snap. — Manoj Srivastava, author of kernel-package

You can use any version of the kernel sources you wish; I chose 2.4.18 because it's the most current in Woody. Debian maintainers have done an excellent job packaging kernel sources into .deb files, and I recommend you use those rather than other source packages. The only reason I can see to use other kernel source packages is to get hardware support not available in Debian.

If you're compiling a 2.2 series kernel for the PC architecture (machines with AMD processors are PCs, but not Macs or Alphas) you'll need the bin86 package.

Installing these packages will cause several other packages to be installed to satisfy dependencies.

You can install these packages by doing (as the root user):

kernel-source-2.4.18 (or whatever kernel sources you will be using)

We will be working with Debian 3.0r1 (Woody revision 1); you will need the following packages:

Replace path_to_kernel with the appropriate information, such as "/boot/vmlinuz-2.4.18-bf2.4" (if you installed Woody with the 2.4 kernel).

Before you make a new kernel the first thing to do is make a boot disk for the kernel you're running. This way, if anything gets screwed up you'll be able to boot the machine and fix it. Grab a floppy disk you don't mind erasing and do this (as the root user):

If you're using sources from kernel.org or from the Debian testing or unstable branches, you may need to update some of your tools to meet the minimal requirements. If you're using sources from the Debian stable branch the above should have been a mere formality. Now that you have the source tree set up you can configure the kernel.

If you can't determine program versions on your Debian system using the above methods, try using dpkg.

Instead of checking for each required program individually, you can run the script ver_linux , which is found in the scripts directory of the kernel tree. You'll need to make it executable first. Note that the script may not check all the requirements listed in Changes , and that it checks for some programs not listed.

The Changes document lists a required program in the first column, the required version in the 2nd, and a command to check the version in the 3rd. You may not need all the programs/packages listed. (For example you don't need pcmcia-cs if you don't use PC cards.)

Inside the linux directory you should find another called Documentation . Change into that directory and look for the file Changes . Open it with your favorite text editor and look for the section "Current Minimal Requirements". Here's an excerpt from mine:

It's a good idea to double-check symbolic links, so do "ls -l". It should look like the example below.

Substitute the name of the directory created when you expanded your kernel source for "kernel-source-2.4.18".

There should not be a symlink pointing to any kernel source tree; it's time to create that link now.

This should create a directory called kernel-source-2.4.18/ owned by you and the src group.

If you have gzipped kernel sources (the filename ends in gz instead of bz2 ) use z instead of j as an option to tar .

To expand the source tarball do this as a regular user:

Debian kernel source packages expand to a directory named kernel-source-x.y.z/ . "Official" kernel sources for kernels up to 2.4.18 expand to a directory called linux/ . (We recommend moving that directory to linux-x.y.z/ .) "Official" sources for kernels 2.4.19 and later expand to linux-x.y.z/ .

If you have that symlink and don't remove it before expanding your new source tarball, you may get a mess of old and new source files which won't compile correctly.

If you also see a symbolic link called linux remove it:

As a normal user, change to the directory /usr/src and list its contents; you should see the bzipped tar file you installed:

You should see "src" among the groups listed. (By default, you also belong to the one-user group "my_username".)

To make sure you were actually added to the src group, issue this command (once you've done the logout/login dance):

If you're at a console just log out and log back in.

If you're using a graphical login manager like xdm, gdm, or kdm, log out of X and back in again.

If you're at a terminal window inside X, log out of X and logout from the console. Then log in at the console and start another X session.

Of course, substitute your own user name for "my_username". Your group memberships are checked during login, so you need to logout and login again to be recognized as a member of src. Here are three ways to do so:

When a kernel source package is installed, the source tarball is placed in the /usr/src directory. To work in this directory, you must be the either the root user or a member of the src group. To avoid doing things as root whenever possible, add yourself to src. Only the root user can add users to groups, so become root and do the following:

"Source tree" is just a term for the directory which contains the source code you will be compiling.

Now exit "make config". You don't want to answer as many as ~1300 different questions one at a time, and there's very little chance you'd get a configuration you could live with anyway. Much better is to use either xconfig or menuconfig.

Kernel 0.01 had no configuration at all, because there were no options. Kernel 1.0 had 49 different options, so a configuration mechanism was needed. Enter "make config".

For this reason many of us encourage kernel newbies to use xconfig, and try menuconfig later when they're more familiar with kernel configuration.

The options are the same as you'd see in xconfig, with one crucial difference -- there's no way to "grey out" an option in menuconfig. If you don't select "Prompt for development or incomplete code/drivers", you won't even see the options for Firewire or Bluetooth.

If you start menuconfig in a longer terminal window, you'll be able to see more categories without scrolling. Menuconfig opens to the size of the terminal you start it from.

Perhaps you aren't using X. Perhaps you're getting better at this configuration business, and your trusty keyboard is faster than a mouse. (Maybe your cat is a little too efficient.) Menuconfig may be just the tool for you.

Notice that the "IEEE 1394 ..." and "Bluetooth support" buttons are greyed out. They are not available because they depend on another option which has not been enabled. Click on "Code maturity level options" and change "Prompt for development and/or incomplete code/drivers" to "y". Now click the "Main menu" button, and notice how the IEEE and Bluetooth buttons can be selected just like the others. Anywhere you see an option that's greyed out, it depends on another option that has been disabled somewhere else.

There are several ways to configure the kernel. The first one we will cover is called "xconfig". Once you've changed to the /usr/src/linux directory, start it like this:

Unfortunately a detailed explanation of kernel options is well beyond the scope of this document. To find out more about configuring the kernel, please see The Linux Documentation Project's "Kernel-HOWTO" , the files in /usr/src/linux/Documentation , and your hardware documentation. Search the archives of the debian-user mailing list , and ask questions there if you don't find answers in the archives. Remember that "Google is your friend."

Be sure (!) that you build floppy disk support into the kernel. If you compile it as modules you won't be able to boot with your new kernel from a floppy disk.

Apart from larger and larger sizes, another feature of recent kernel images is their use of initrd. A special dictionary I keep next to my computer defines initrd as "one more thing to worry about". You can avoid the need to worry about initrd by ensuring that you compile directly into the kernel (not as modules) support for your boot hardware and root filesystem. If the hard drive you boot from is IDE, compile IDE support into the kernel. If your root filesystem is Reiserfs be sure Reiserfs support is built not as modules but directly into the kernel.

Kernel size depends on configuration. My kernel 2.4.18 was 645 KB; the kernel I built using Debian's 2.4.18-bf2.4 configuration was 1228 KB.

To make their kernels useable by most people on most hardware, Linux distributors generally include support for most hardware and functions. Debian is no different; pre-compiled kernels include support for hardware you'll never have and languages you'll never read. My general rule for kernel configuration is, "If in doubt leave it out." If you test your new kernel and find that some of your hardware doesn't work, it's easy to tweak the configuration and build another kernel.

An important principle of kernel configuration is TANSTAAFL (There Ain't No Such Thing As A Free Lunch). Any features you add to the kernel increase its size (and the time to build it), even if you choose to add them as modules.

Now all you can do is wait for the computer to finish. Take a few minutes off and enjoy yourself while the computer does its fair share of the work.

The manual page for make-kpkg describes one way to use fakeroot; we will use the simpler method of putting "fakeroot" at the beginning of the make-kpkg command line, like this:

Using fakeroot you can start make-kpkg as a normal user, and most of the job will be run with normal permissions. Near the end of the job, fakeroot will simulate a root environment to create the kernel-image package.

When you added yourself to the src group you made it possible to do most kernel-package work with normal user privilege. However the files that are part of a kernel package (like the kernel and kernel modules) will be owned by root and run with root privilege; they must be created with root privilege.

Please read /usr/share/doc/kernel-package/README.gz if --append-to-version or --revision is unclear, or if you plan on using options different from the ones I suggest. (One way to do this is "zcat README.gz | most".) Ignore the discussions of flavours and epochs until you are more familiar with make-kpkg and with Debian packages generally; they are not likely to be useful to you now.

I recommend using a different --append-to-version value for each kernel you compile, and letting make-kpkg assign the default revision. Date-based values work for me, but you are free to invent your own scheme.

I have two revisions of kernel 2.4.18.030320: revision 1.0 and revision 10.00.Custom. If I install either of these kernels and later try to install the other I will get a warning about conflicting kernels/modules. If I continue I will overwrite the already-installed kernel and its modules.

I have two kernel names : 2.4.18.030309 and 2.4.18.030320. I can install both without worrying about conflicts.

Now you can see why underscores are not allowed in make-kpkg options — they separate the elements of package names.

The package name is everything before the first underscore. Here is a partial list of my kernel packages:

You will not be using --revision in this tutorial.

Using different values of --revision will not prevent conflicts between kernels with the same name.

Another make-kpkg option is "--revision", which affects the name of the Debian package itself but not the kernel name. As with --append-to-version, you may use only alphanumeric characters, "+" and ".". Do not use underscores "_". If you do not supply a value for --revision, make-kpkg will use "10.00.Custom".

If you install a kernel with the same name (the same version and --append-to-version) as an already-installed kernel, installing the new kernel package will overwrite the old kernel and its modules. You will be warned and offered the chance to abort. Take it. Use another value for --append-to-version and rebuild.

This means that by using a new value for --append-to-version each time you build a kernel image, you can ensure that the new kernel will have a new name, and that its modules won't conflict with those of other kernels.

Kernel modules live in subdirectories of /lib/modules ; each kernel has its own subdirectory. Every time you install a kernel image with a new name, the package installer creates a new subdirectory of /lib/modules to hold its modules.

You should avoid using --append-to-version values such as "-686", "-K7", and "-sparc". They are commonly used for Debian pre-compiled kernels.

I used "--append-to-version=.030309" (note the leading ".") when I built the image for this kernel. It's shorthand for "2003 March 09", and it's my way of distinguishing this kernel from other 2.4.18 kernels (such as kernel 2.4.18.020724 which I built on 2002 July 24).

The first option lets you specify an addition to the kernel version, which then becomes part of the kernel's name. You may use alphanumeric characters, "+" and "." (period or full stop); do not use underscore "_".

Your target will be "kernel_image". Let's examine two of the more important and common options, "--append-to-version" and "--revision".

The make-kpkg command line can be complex and at first intimidating. Its basic syntax is

make-kpkg is part of the "kernel-package" package. Its documentation is located in /usr/share/doc/kernel-package/ .

To build the kernel you'll invoke "make-kpkg", a script which automates and replaces the sequence "make dep; make clean; make bzImage; make modules". Take a few minutes and read over the manual page for make-kpkg.

If you have an older machine with a slower processor it can take several hours to build a Debian kernel image. (It is possible to build your kernel on a faster machine and install it on the slower machine, but I won't cover that here.) I built a kernel 2.4.18 package on my high-speed low-drag 166 MHz Pentium and it took about 1 hour 40 minutes. That was using my configuration. Using Debian's kernel 2.4.18-bf2.4 configuration, it took 4 hours 45 minutes on the same machine. On a 1GHz Pentium III the same packages built in 9 and 23 ½ minutes, respectively.

Congratulations on compiling your first kernel with kernel-package. No sweat eh? There are still a few things you should do before you declare victory and fire up Quake III.

If everything went well, all you need to do now is reboot. If your new kernel doesn't boot, insert your boot floppy and restart. Go back to Configuring the kernel , tweak your configuration, and try again.

If you use grub see Kernel-package and grub .

If you say "yes", you'll be prompted to install a partition boot record, install a master boot record, and make your root partition the active partition.

If you are using a bootloader other than lilo you should check the documentation in /usr/share/doc/kernel-package before answering this question. You probably will not want the post-install script to handle your bootloader.

Be sure you say "no" when the script asks if you want to install a boot block using the existing /etc/lilo.conf . That would be trying to boot the new kernel with the old configuration, and it won't work. Next you'll be asked if you want to wipe out the old LILO configuration and make a new one. If you use LILO that would be "yes". Then you'll be asked whether you want to set up Linux to boot from the hard disk.

If you haven't made a boot disk yet then you need to do so. If the post-install process whacks lilo you will not be able to restart without a boot floppy.

The post-install script should ask if you want to make a boot disk. If you made one earlier you can say "no" here. Otherwise grab a floppy you don't mind erasing and say "yes".

To install a kernel-image package from disk (as opposed to installing from a Debian archive) use the full file name .

To install the kernel and all its modules become root and do:

Once the kernel image is built you will install the kernel-image package, which includes the kernel and its modules. First check to make sure it was built successfully by changing to the /usr/src directory and listing its contents:

If you want to rebuild your kernel because you just bought a new sound card, or you want to enable a new feature you forgot to include the first time, all you need to do is reconfigure, do "fakeroot make-kpkg clean", and rebuild with a different value for --append-to-version. Your session should look something like this:

If the modules subdirectory still isn't empty, you probably have kernel modules that you didn't build with make-kpkg. You can remove the modules subdirectory once you're satisfied there's nothing there you need.

If you get a message that "/lib/modules/2.4.18.030309 is not empty so wasn't removed", you probably have third-party modules installed there. They too can be removed by purging their packages. (See Third-party modules to find out how to make them with make-kpkg.)

Now that you see how easy it is to build and install kernels, it won't be long before your /boot directory is crowded with kernels and configs and System.maps. Use dpkg to purge the ones you don't need:

Create another boot diskette, this one for the kernel you just installed. Grab another floppy — it's not a good idea to overwrite your old boot disk; you haven't been using your new kernel long enough to be sure it works.

Once your kernel has been packaged with its modules, you can install it on any machine that has the hardware you specified in your kernel configuration. You could even reinstall it on your current machine after reinstalling your system.

While not required, it's a good idea is to back up your custom kernel .deb. Copy it to a secure undisclosed location.

When you download patches or other source code into a specific source tree, you don't want anything else messing with it. By removing the symlink you might prevent #1 from happening.

The next time you download the kernel source from the Debian archive, you might expand the source into its own tree without problems. But since you already have a symlink called "linux" in the src directory, you might go ahead and compile (forgetting of course that it's linked to your old source tree.)

The next time you download a kernel it might not be from a Debian archive. When you expand the source tarball it could overwrite your old source tree right through the old symlink. Bummer.

Next, you should get rid of the symlink you created in the /usr/src directory. There are several reasons for this:

Of course substitute the real name of your kernel. To refer to a package that dpkg knows about (an installed package or one in an archive's list) use the package name rather than the full file name. Also, the "|" character is made by typing Shift - \ . Check that the package really is on hold; if it is you should see:

If you used --append-to-version you shouldn't need to worry about apt-get trying to "upgrade" your kernel. If you're paranoid (it is out to get you) you can make sure by doing this (as root):

It may seem a bit strange to have a page for "Advanced topics" in a newbiedoc. We know that some of our readers aren't new to Linux or even to building kernels; they are trying to learn The Debian Way to administer their systems. Once you have successfully used kernel-package to build and install your own custom kernel, you may want to explore some ways to make life even better.

8.1. Using an existing configuration When you installed your custom kernel, its configuration was copied to /boot/config-x.y.z . You may want to squirrel it away in another location (or several other locations) for safekeeping or later re-use. Suppose that just last week you picked your way through the maze of options, and settled on a configuration that supports all the hardware and features you want. Today a new stable kernel is released and of course you want to upgrade right away. Is it necessary to start from scratch configuring the new kernel? Not at all. Download and expand the new source tarball and make a new symlink. Then change directories to /usr/src/linux , copy your existing configuration there and do "make oldconfig": bash:/usr/src/linux$ cp /boot/config-2.4.18.030320 .config bash:/usr/src/linux$ make oldconfig You'll be asked questions about new kernel options. It's generally safe to answer "no" to all the questions; make notes of the new options that interest you. After you finish oldconfig you can run xconfig or menuconfig to review your selections, change your answers, or investigate the options you noted. Then do "fakeroot make-kpkg clean" and you're ready to build the latest stable kernel with your own configuration.

8.2. Kernel-package and grub Although LILO is still Debian's default boot loader, grub is an outstanding alternative, and it works and plays well with make-kpkg. After you've installed grub, run "grub-install /dev/hda" (substitute your boot device for "/dev/hda"). Then run "update-grub". Edit /boot/grub/menu.lst and substitute your defaults on the "#groot" and "#kopt" lines (and any other lines you need for your situation). Run "update-grub" again. Create the file /etc/kernel-img.conf and insert the following lines: postinst_hook=/sbin/update-grub

postrm_hook=/sbin/update-grub

Now whenever you install a new kernel image, update-grub will scan your /boot directory, inventory the kernels there, and write a new boot menu. If you took my suggestion and used "--append-to-version=.yymmdd", your kernels will be sorted by kernel version and date. The grub default is to start the first kernel in the list (your newest kernel), unless you choose a different one before the menu times out. When you remove a kernel, update-grub will remove its entry from the boot menu. When you're comfortable with grub, do "dpkg -P lilo" and you won't be asked about lilo when you install a new kernel. :)

8.3. Third-party modules "Third-party modules" is the term I use for kernel modules with source code outside the kernel source tree. An example is "pcmcia-cs", which many laptop users need for the latest PCMCIA support. To use pcmcia-cs, apt-get the "pcmcia-source" package; the source tarball should be in /usr/src . As a normal user, expand the source tarball to /usr/src/modules/pcmcia-cs . If you don't already have a modules directory one will be created. When you configure your kernel, disable PCMCIA support. (If you have PCMCIA support enabled, pcmcia-cs won't build drivers.) If you want to use wireless LAN, enable it under "Network device support" but don't select any devices. When you are ready to build your kernel, add "modules_image" to your command line: bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030401 kernel_image modules_image (As you learn more and more the make-kpkg command line gets longer and longer.) After your kernel-image .deb is made, make-kpkg will go to /usr/src/modules and build a modules .deb for each subdirectory, with the same version and --append-to-version as your kernel. Install the modules-image .debs after you install the kernel-image .deb. That's it. Could this get any easier?

8.4. Adding third-party modules to an existing kernel You've been monitoring the debian-user mailing list, and you notice that more and more people are interested in alsa (Advanced Linux Sound Architecture). You realize that your new sound card doesn't sound as good as it should, and you want to try alsa yourself. You fire up "make menuconfig" (you are more experienced now) but in the "Sound" section you don't see anything labelled "alsa". What to do? Install the "alsa-source" package. By now you know to look for a new tarball in /usr/src , and there it is: bash:/usr/src$ ls alsa-driver.tar.bz2 kernel-image-2.4.18.030401_10.00.Custom_i386.deb kernel-source-2.4.18 kernel-source-2.4.18.tar.bz2 modules pcmcia-modules-2.4.18.030401_3.1.33-6+10.00.Custom_i386.deb Expand the alsa-driver tarball and re-create the symlink. Note the --append-to-version value of your kernel image; you'll need it as an option for make-kpkg: bash:/usr/src$ cd linux bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030401 --added-modules=alsa-driver modules_image Notice that you don't need the "kernel_image" target here. Unless you reconfigured the kernel, there's no need to rebuild it. Using the "--added-modules" option lets you build only the modules you need, instead of all the modules in /usr/src/modules . If you want to build a modules .deb with a different --revision than the kernel, you may need to appease make-kpkg by doing "fakeroot make-kpkg clean".