Advice on building and deploying a custom kernel?

Hello!

I am trying to build a custom image for some ARM64 SBCs. This comes with some challenges. I won’t go over all of them unless someone is interested, but one of them is that all the Universal Blue OCI images are only distributed for x86_64 as far as I could find, which is why I am using Silverblue as base for now instead of Universal Blue.
The main topic of this thread however is the kernel challenge. I need to build and install a custom kernel with the following implications:

  • building with a customized kernel config
  • possibly adding some patches to the kernel source code
  • remove the existing kernel in the image and replace it by installing the custom built one
  • do all the configuration that the kernel can load (e.g. put the correct files in the correct locations, generating an initramfs)
  • have the build automated for new upstream versions and be able to update it on the systems by normal update means (ostree updates I guess?)
  • kernel source can be the Fedora kernel source or the main source from kernel.org, it doesn’t matter to me (unless there’s something cool about the Fedora-specific kernel source?)

What I am doing right now as proof-of-concept is building the kernel source from kernel.org locally using a little script and then package it into an rpm with a slim .spec file. The rpm package is then installed with the Containerfile.

A snippet of my .spec file:
(keep in mind that this spec file does not do the kernel building, but only package the compiled files)

%install
# Create necessary directories
mkdir -p %{buildroot}/boot
mkdir -p %{buildroot}/boot/dtbs-%{version}-%{variant}
mkdir -p %{buildroot}/lib/modules/%{version}-%{variant}

# Install the kernel image, config, and System.map
install -m 644 %{SOURCE0} %{buildroot}/boot/vmlinuz-%{version}-%{variant}
install -m 644 %{SOURCE1} %{buildroot}/boot/.config-%{version}-%{variant}
install -m 644 %{SOURCE2} %{buildroot}/boot/System.map-%{version}-%{variant}

# Copy the unpacked DTBs to the build root
cp -r %{_builddir}/%{name}-%{version}/dtbs/* %{buildroot}/boot/dtbs-%{version}-%{variant}

# TODO: figure out where the built modules live
# cp -r /path/to/modules/* %{buildroot}/lib/modules/%{version}-%{variant}/

%post
# Update module dependencies
/sbin/depmod -a %{version}-%{variant}
dracut --no-hostonly --force --kernel-cmdline "console=ttyS2,1500000" /boot/initramfs-%{version}-%{variant}.img %{version}-%{variant}

(yes, the modules should probably be a different package than the kernel itself, maybe at a later stage)

And then in the Containerfile, which is using Fedora Silverblue 40 (aarch64) as base (partly generated with blue-build):

RUN \
--mount=type=bind,from=stage-files,src=/files,dst=/tmp/files,rw \
  --mount=type=cache,dst=/var/cache/rpm-ostree,id=rpm-ostree-cache-blue-test-40,sharing=locked \
  rpm-ostree override remove kernel kernel-core kernel-modules kernel-modules-extra kernel-modules-core \
  && rpm-ostree install /tmp/files/*kernel*.rpm \
  && ostree container commit \

Do you have any advice on how my current build-and-deployment-process could be improved?
If I publish a custom image flavor that also others may use, it’s probably nice to use best practices from the beginning :slight_smile:
Thanks a lot! <3