How To Build a Distributable Fedora Custom Kernel on Fedora

Joey Morrow
5 min readMay 24, 2019

--

If you find yourself needing to build a distributable Custom Kernel for Fedora, you’ve found the place! Two reasons I can think of for why you might need to build and know how to apply a Fedora Custom Kernel are as follows:

  • Your Target platform doesn’t have enough disk space to build the kernel (~20–30+ GB)
  • You need to apply a kernel patch to a bunch of machines (custom IT support)

For me, I fell into the former case.

If you’re looking for how to do this on Fedora IoT, please go here instead.

Requirement: Your Target and Build platforms should use the same architecture. (Both of my platforms utilize “x86_64” architecture which means these platforms use Intel CPUs.) (You may be able to do some tricky stuff to cross-compile across architectures, but good luck! :P)

This article is split up into 7 steps. (2hr30min of your computer’s time & 35min of your time)
1. Discovery (~15–20 min)
2. Retrieval (~5 min)
3. Unpack (~3 min)
4. Setup (~3 min)
5. Customizations (~1+ min)
6. Build (~2 hours)
7. Install (~5 min)

Only steps 1 & 7 are done on the Fedora Target system. Everything else is done on the Fedora Build system.

1. Discovery (Run on Target system.)

Figure out what we need to figure out- Namely, what kernel version are we downloading? If you already know, you can skip down to section “Retrieval.”

a. Download Fedora to your platform. Follow directions found at https://getfedora.org/. We will be upgrading the stable version of the kernel to our custom kernel, rather than doing a fresh install. So this requires you to install Fedora first. Come back here once your Fedora installation is up.
b. Create your user account on the Target platform.
c. Run: “dnf update”. (This will ensure your kernel is at the latest stable version.)
d. Run: “systemctl reboot”
e. Once Fedora system reboots, run: “uname -r”
(Mine was “5.0.16–200.fc29.x86_64”.)
(Disambiguation: “<Version>-<Release>.<Architecture>” ==> Version=5.0.16, Release=200.fc29, Architecture=x86_64)

This is the kernel version you’re targeting.

2. Retrieval (Run on Fedora Build system.)

Now that you know the version of the kernel you want to build, you can retrieve it! Fedora publishes the source code!

a. dnf download --source kernel-<Version>-<Release>.<Architecture>
(Mine was “dnf download kernel-5.0.16–200.fc29.x86_64”.)
(If your Build system and Target systems have the same value for the command “uname -r” you may use “dnf download --source kernel-$(uname -r)”.)

Notice: This downloads a *.rpm file to the current directory. If you want to download this rpm file to a specific location, either ‘cd’ to that directory or read up on the “dnf download” command to figure out where to direct the download output of this command.

3. Unpack (Run on Fedora Build system.)

Now that you have the Kernel Source, you can unpack it for the ‘rpmbuild; utility to build. The last command unpacks the *.src.rpm file into ~/rpmbuild/*. (Notice you may have multiple rpm packages unpacked at this location. In this case, please be sure to recognize the files you’re touching if you have more than one rpmbuild or kernel you’ve built.)

$ useradd mockbuild

$ groupadd mock

$ rpm -Uvh kernel-<Version>-<Release>.src.rpm

(For me it was “rpm -Uvh kernel-5.0.16–200.fc29.src.rpm”)

4. Setup (Run on Fedora Build system.)

Now that you have all the contents to build the kernel, you need to make sure your Fedora system is capable of building the kernel. You will need to install the following components.

$ sudo dnf install rpmdevtools ncurses-devel

$ rpmdev-setuptree

At directory ~/rpmbuild/SPECS/ you will need issue the following command:
$ sudo dnf builddep kernel.spec

5. Customizations (Run on Fedora Build system.)

Before you build it’s best to make at least one suggested change. This is where you make any changes to the Sources. (Sources and Configurations are found in ~/rpmbuild/SOURCES.)

  1. Modify the “baserelease” value in <kernel-<Version>–<Release>.src>/kernel.spec to something higher than 300.
    Note: Fedora’s Official Build System apparently uses values “100”, “200”, and “300” already. It’s suggested to change this value, but you could choose to change other versioning information instead. If you don’t make any name or versioning changes the Fedora Target system will reject this kernel as it thinks the kernel is already installed. I chose to change the value to “700” arbitrarily.
  2. This is also where you would make any changes to kernel build flags. You will want to modify the flags found in “kernel-<Architecture>.config.”
    (For me, I modified “kernel-x86_64.config.”)

6. Build (Run on Fedora Build system.)

Now that your build environment and customizations are ready to go, you can build the kernel! (Notice: I issue these commands from ~/rpmbuild/SPECS directory.)

$ rpmbuild -bs --target x86_64 --nodeps kernel.spec

$ rpmbuild -bb --target x86_64 --nodeps kernel.spec

Notice: This build will take ~2 hours on latest generation Intel Core I7 4 core CPU from the second command “-bb” above.
Notice: The build output is now located at $HOME/rpmbuild/*.

Copy the contents of “$HOME/rpmbuild/RPMS/*” to a flashdrive. Alternatively, you can use your favorite file sharing technique (eg. scp). This is just what I did. (Notice you may have multiple rpm packages unpacked at this location. In this case, please be sure to recognize the files you’re copying if you have more than one rpmbuild or kernel you’ve built.)

You can issue the commands with the time utility to see how long the build took by prepending “time” to your command like “$ time rpmbuild …”. The resulting time will be printed after the build completes.

7. Install (Run on Fedora Target system.)

Now copy the RPMs you copied on the flash drive to the Fedora Target system.

Now issue the following commands at the location you pasted to:

$ dnf install ./kernel-<Version>-<Release>.<Architecture>.rpm ./kernel-core-<Version>-<Release>.<Architecture>.rpm ./kernel-modules-<Version>-<Release>.<Architecture>.rpm ./kernel-modules-extra-<Version>-<Release>.<Architecture>.rpm
(I did: $ dnf install ./kernel-*)

$ systemctl reboot

If you run into an error at boot stating something along the lines of “vmlinuz has invalid signature,” you will need to disable Secure Boot in your system’s BIOS and then restart your system for the time-being. I am currently troubleshooting how to sign the custom kernel and upload the keys into the BIOS to validate your custom kernel for use.

$ uname -r

The output of “uname -r” should match your custom built kernel! Have fun! :D

--

--