Build a custom kernel package for Debian

Last modified on 2019-09-22

Perhaps it is hardware unsupported by any of the Linux kernels provided by Debian. Or trying to troubleshoot a kernel’s misbehaviour by running the latest and greatest. Or a desire to try out a brand new kernel capability. Or simple curiosity!

Whatever the reason, this is how I build a custom kernel package for Debian from the “vanilla” kernel source available on

Let’s go!

0. Download build tools …

$ sudo apt install build-essential bison flex gnupg libncurses-dev libelf-dev libssl-dev wget

1. Import crypto signing keys belonging to kernel release developers …

$ gpg --locate-keys

2. Download to my home directory the latest stable kernel source and signature (5.3 as of 2019-09-22) …

$ mkdir ~/kernel
$ cd ~/kernel
$ wget
$ wget

3. Verify …

$ unxz -c linux-5.3.tar.xz | gpg --verify linux-5.3.tar.sign -
gpg: Signature made Mon 16 Sep 2019 02:01:09 AM EDT
gpg:                using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E

4. Unpack kernel …

$ tar xaf linux-5.3.tar.xz
$ cd linux-5.3

5. Rather than configure everything from scratch, copy the /boot/config-VERSION of the kernel currently in use to the kernel source directory …

$ uname -r
$ cp /boot/config-5.2.0-2-amd64 ~/kernel/linux-5.3/.config

6. If anything needs to be modified in the configuration, bring up the configuration menu by running …

$ make nconfig

Otherwise, when using a .config file that has been generated with another (older) kernel version, it needs to be updated with any changes that have been been made to the newer kernel. Running …

$ make oldconfig

… interactively asks questions relating to the new options.

To preemptively accept the default answer to all those questions, run …

$ make olddefconfig

7. Modify the copied Debian kernel configuration and set …


… or the build fails with the error …

make[4]: *** No rule to make target 'debian/certs/debian-uefi-certs.pem', needed by 'certs/x509_certificate_list'.  Stop.

8. Optional: Skip building the linux-image-VERSION-dbg package which contains the debugging symbols for the kernel image and its modules. Not required unless debugging kernel code. Significant savings in compile time and space. Building binary packages for a single kernel flavour that includes *-dbg package requires upwards of 24GB of space in the package directory vs roughly 3-4GB without.

To disable the build of *-dbg package, modify the configuration by setting …


9. Build the kernel (LOCALVERSION parameter appends custom text to the generated package name) …

$ make clean
$ make deb-pkg LOCALVERSION=-custom

10. New packages …

$ ls ../*deb
../linux-headers-5.3.0-custom_5.3.0-custom-1_amd64.deb      # header files required to build external modules
../linux-image-5.3.0-custom_5.3.0-custom-1_amd64.deb        # kernel image and the associated modules
../linux-image-5.3.0-custom-dbg_5.3.0-custom-1_amd64.deb    # if CONFIG_DEBUG_INFO=y
../linux-libc-dev_5.3.0-custom-1_amd64.deb                  # headers relevant to some user-space libraries like GNU glibc

Install …

$ sudo dpkg -i ../linux-image-5.3.0-custom_5.3.0-custom-1_amd64.deb

… which unpacks the kernel, generates the initrd, and configures the bootloader to make the new kernel the default one.

11. Resources:

Reboot and enjoy!