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
Thanks a lot! <3