Building the Linux Kernel
Building the kernel yourself lets you enable experimental features, apply custom patches (like PREEMPT_RT), shrink the kernel for embedded systems, or simply understand how it all fits together. The process takes about 30 minutes on modern hardware.
Getting the Source
# Official source: kernel.org
# Download latest stable tarball:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.tar.xz
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.tar.sign
# Verify GPG signature (optional but good practice):
xz -d linux-6.12.tar.xz
gpg --verify linux-6.12.tar.sign linux-6.12.tar
# Extract:
tar xf linux-6.12.tar
cd linux-6.12
# Or clone with git (full history, ~4GB):
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
# Stable branch (production-ready point releases):
git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
git checkout linux-6.12.y
Build Dependencies
# Ubuntu/Debian:
apt install build-essential libncurses-dev bison flex libssl-dev \
libelf-dev dwarves bc make gcc pkg-config
# Fedora/RHEL:
dnf install gcc make ncurses-devel bison flex openssl-devel \
elfutils-libelf-devel dwarves bc
# Verify gcc works:
gcc --version
make --version
# Optional: ccache speeds up repeated builds
apt install ccache
export CC="ccache gcc"
Building the Kernel
# Build everything (kernel + all modules):
# -j$(nproc) uses all CPU cores in parallel
make -j$(nproc)
# Build output:
# arch/x86/boot/bzImage ← compressed kernel image
# *.ko files throughout ← kernel modules
# Build time estimates (on modern 8-core machine):
# make localmodconfig build: ~5-10 minutes
# make olddefconfig build: ~20-40 minutes
# Full allmodconfig build: ~2+ hours
# Watch build with verbosity (debug build failures):
make -j$(nproc) V=1 2>&1 | tee build.log
# Build just a specific module (fast):
make -j$(nproc) drivers/net/ethernet/intel/e1000/e1000.ko
# Cross-compile for ARM64 (e.g., building for Raspberry Pi on x86):
apt install gcc-aarch64-linux-gnu
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make -j$(nproc)
Installing the Kernel
# Install kernel modules to /lib/modules/VERSION/:
sudo make modules_install
# Install kernel image + update initramfs + update GRUB:
sudo make install
# This runs installkernel script which:
# 1. Copies bzImage to /boot/vmlinuz-VERSION
# 2. Copies System.map to /boot/System.map-VERSION
# 3. Copies .config to /boot/config-VERSION
# 4. Generates initrd/initramfs: update-initramfs -c -k VERSION
# 5. Updates bootloader: update-grub
# Verify files are in /boot:
ls /boot/ | grep $(make kernelversion)
# config-6.12.0-custom
# initrd.img-6.12.0-custom
# System.map-6.12.0-custom
# vmlinuz-6.12.0-custom
# GRUB should now list the new kernel:
grep menuentry /boot/grub/grub.cfg | head -5
# Reboot and select new kernel from GRUB menu:
sudo reboot
# After reboot — verify:
uname -r
# 6.12.0-custom
Cleanup and Removing a Kernel
# Remove a kernel you no longer want:
# 1. Remove from /boot:
sudo rm /boot/vmlinuz-6.12.0-custom
sudo rm /boot/initrd.img-6.12.0-custom
sudo rm /boot/System.map-6.12.0-custom
sudo rm /boot/config-6.12.0-custom
# 2. Remove modules:
sudo rm -rf /lib/modules/6.12.0-custom
# 3. Update GRUB:
sudo update-grub
# Clean build artifacts (before switching configs):
make clean # removes built files, keeps .config
make mrproper # removes everything including .config
make distclean # removes even editor backup files
# Check build size:
du -sh vmlinux # uncompressed kernel (~100-300MB)
du -sh arch/x86/boot/bzImage # compressed image (~10-15MB)
Frequently Asked Questions
What will I learn here?
This page covers the core concepts and techniques you need to understand the topic and progress confidently to the next lesson.
How should I use this page?
Start with the overview, then follow the section links to deepen your understanding. Use the table of contents on the right to jump to specific sections.
What should I read next?
Use the navigation below to continue to the next lesson or explore related topics.