Maintaining own custom kernel

From Argent Wiki

Maintaining own custom kernel

This page walks through the whole flow of building a custom kernel on Argent and keeping it up to date: our kernel sources with a different config, or a different patched source (linux-tkg, a vanilla kernel with your patches, ...) with your config.

Your kernel becomes two packages in your overlay, built by the same argent-kernel eclass as ours, and installed next to our kernel, not over it. You don't edit our ebuilds, epkg update resets them.

All of it happens in devmode, so read Mixing Binaries and Compiling first if you haven't yet.

How it works

The eclass doesn't download a kernel from kernel.org or from git. It takes a source tarball, unpacks it, finds the kernel config inside it, and builds the kernel with that config. For our kernel, the tarball is linux-6.12.114-argent.tar.xz, downloaded from our server. For yours, it's a tarball you make and keep in /var/cache/distfiles.

That decides the order:

  1. switch to devmode
  2. prepare the source tree and the tarball
  3. create your overlay
  4. write the ebuilds
  5. make the manifests and install
  6. boot it
  7. keep it up to date

The source comes first. The ebuilds, the manifests and the eclass only read what you prepared in step 2. If the source tree, the config or the tarball is wrong, nothing after it works. When something fails later, step 2 is the first place to look.

Pick a name

Pick one name and use it everywhere. On this page it's mykernel, with our 6.12.114 sources:

What Name
packages sys-kernel/linux-mykernel and sys-kernel/mykernel-sources
kernel (uname -r) 6.12.114-mykernel
source tree /var/cache/distfiles/linux-6.12.114-mykernel/
config in the source tree mykernel/config/mykernel-6.12-amd64.config
tarball /var/cache/distfiles/linux-6.12.114-mykernel.tar.xz
both ebuilds K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"

The eclass uses this name for the tarball, the config, the initramfs and the DKMS modules. If one of them still says argent, dracut builds the initramfs for our kernel instead of yours, and removing your kernel deletes ours.

Any name works, except argent, that one is ours.

Where your files are

Path What
/var/cache/distfiles/linux-6.12.114-mykernel/ your source tree with your config, where you work
/var/cache/distfiles/linux-6.12.114-mykernel.tar.xz the tarball portage builds your kernel from
/var/db/repos/myoverlay/sys-kernel/ your ebuilds
/etc/portage/repos.conf/eselect-repo.conf tells portage your overlay exists

Keep the source tree and the tarball in /var/cache/distfiles. It's the DISTDIR in the make.conf of every mode, the only place where portage looks for source archives. Our ebuilds point to our server, yours point to a file that exists only on your disk, so portage has to find it there every time it builds or rebuilds your kernel.

Nothing of ours deletes it: epkg update, epkg clean, epkg wipe and the avasile mode switches leave /var/cache/distfiles alone. It's still the only copy of your kernel, so keep a backup of the source tree and the tarball on another disk.

Step 1: switch to devmode

avasile --devmode

Check it:

avasile --status

It has to say avasile is on --devmode!.

User mode doesn't work for this: it has no ebuilds, so no way to fetch our kernel sources, and it never compiles, while everything from your overlay gets compiled.

A mode switch deletes the whole /etc/portage, your files too. If you already have files there, copy them out before you switch, and put them back after. See Avasile System Management. If compiling fails right after the switch, see missing build tools in devmode.

Step 2: prepare the source

Do this before you write any ebuild. Everything in this step happens in /var/cache/distfiles, as root.

2.1 Get the source tree

From our sources. Download our tarball, unpack it, and give the tree your name:

epkg fetchsourcepkg =sys-kernel/argent-sources-6.12.114

cd /var/cache/distfiles

tar -xJf linux-6.12.114-argent.tar.xz

mv linux-6.12.114-argent linux-6.12.114-mykernel

From another source (linux-tkg, a vanilla kernel with your patches, ...). Put the patched tree in /var/cache/distfiles, named linux-<version>-mykernel. The version is the one the tree reports:

cd /var/cache/distfiles/linux-7.3.1-mykernel

make -s kernelversion

That version goes everywhere else on this page too. For 7.3.1, the ebuilds are linux-mykernel-7.3.1.ebuild and mykernel-sources-7.3.1.ebuild, with K_ROGKERNEL_FORCE_UPPERLEVEL="7.3" and K_ROGKERNEL_FORCE_SUBLEVEL="1", and the config is mykernel-7.3-amd64.config.

2.2 Make your config

cd /var/cache/distfiles/linux-6.12.114-mykernel

Start from our config. From our sources, it's already in the tree:

cp argent/config/argent-6.12-amd64.config .config

For another source, take it out of our tarball (download it with epkg fetchsourcepkg as above), and let the kernel adapt it to its version:

tar -xJOf /var/cache/distfiles/linux-6.12.114-argent.tar.xz linux-6.12.114-argent/argent/config/argent-6.12-amd64.config > .config

make olddefconfig

Then change what you want:

make menuconfig

2.3 Put the config where the eclass looks for it

The eclass looks for <name>-<major.minor>-amd64.config in the <name>/config/ directory of the tree:

mkdir -p mykernel/config

cp .config mykernel/config/mykernel-6.12-amd64.config

Remove our config directory (it's there only if you started from our sources), and clean the tree, so the tarball doesn't carry your build files:

rm -rf argent

make mrproper

2.4 Check the tree

ls /var/cache/distfiles/linux-6.12.114-mykernel/mykernel/config/

It has to show mykernel-6.12-amd64.config. The tree looks like this now:

/var/cache/distfiles/
└── linux-6.12.114-mykernel/
    ├── Makefile
    ├── arch/
    ├── ...
    └── mykernel/
        └── config/
            └── mykernel-6.12-amd64.config

2.5 Pack the tarball

Pack it from /var/cache/distfiles, with a relative path, so the tarball starts with the tree:

cd /var/cache/distfiles

tar -pcJf linux-6.12.114-mykernel.tar.xz linux-6.12.114-mykernel

Check it, the first line has to be linux-6.12.114-mykernel/:

tar -tJf linux-6.12.114-mykernel.tar.xz | head -1

If it shows var/cache/distfiles/..., the tarball was packed with the full path, pack it again from /var/cache/distfiles as above.

Keep the tree next to the tarball, you need it for every config change.

Step 3: create your overlay

eselect repository create myoverlay

The overlay is in /var/db/repos/myoverlay. Your ebuilds use the argent-kernel eclass from argent-ws, so your overlay has to see it. /var/db/repos/myoverlay/metadata/layout.conf has to contain:

masters = gentoo argent-ws
thin-manifests = true

eselect repository registers the overlay in /etc/portage/repos.conf/eselect-repo.conf. That file survives epkg update, but a mode switch removes it, so keep a copy.

Step 4: write the ebuilds

cd /var/db/repos/myoverlay

mkdir -p sys-kernel/linux-mykernel sys-kernel/mykernel-sources

sys-kernel/linux-mykernel/linux-mykernel-6.12.114.ebuild:

EAPI=8

K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_REQUIRED_LINUX_FIRMWARE_VER="20260622"
K_ROGKERNEL_FORCE_SUBLEVEL="114"
K_ROGKERNEL_FORCE_UPPERLEVEL="6.12"
K_ROGKERNEL_PATCH_UPSTREAM_TARBALL="0"
K_KERNEL_NEW_VERSIONING="1"

inherit argent-kernel

KEYWORDS="amd64"
DESCRIPTION="Custom kernel image"
RESTRICT="mirror"
IUSE="grub2"

sys-kernel/mykernel-sources/mykernel-sources-6.12.114.ebuild:

EAPI=8

K_ROGKERNEL_FORCE_SUBLEVEL="114"
K_ROGKERNEL_FORCE_UPPERLEVEL="6.12"
K_ROGKERNEL_NAME="mykernel"
K_ROGKERNEL_URI_CONFIG="yes"
K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_ONLY_SOURCES="1"
K_KERNEL_NEW_VERSIONING="1"

inherit argent-kernel

KEYWORDS="amd64"
DESCRIPTION="Custom kernel sources"
RESTRICT="mirror"
IUSE="grub2 sources_standalone"

DEPEND="${DEPEND}
	sources_standalone? ( !=sys-kernel/linux-mykernel-${PVR} )
	!sources_standalone? ( =sys-kernel/linux-mykernel-${PVR} )"

What's different from our linux-argent and argent-sources:

  • K_ROGKERNEL_SELF_TARBALL_NAME is mykernel in both
  • K_ROGKERNEL_NAME is mykernel in the sources ebuild (in linux-mykernel it comes from the package name)
  • the sources depend on linux-mykernel, not on linux-argent

The download address in the ebuilds points to our server, where your tarball doesn't exist. That's fine, portage finds it in /var/cache/distfiles and doesn't download anything. It's also why the tarball has to stay there.

Optional: keep your config next to the ebuilds

The config inside the tarball is enough. If you'd rather change the config without packing the tarball again, keep a copy in files/ of both packages, and let src_prepare() copy it over the one from the tarball:

mkdir -p sys-kernel/linux-mykernel/files sys-kernel/mykernel-sources/files

cp /var/cache/distfiles/linux-6.12.114-mykernel/mykernel/config/mykernel-6.12-amd64.config sys-kernel/linux-mykernel/files/

cp /var/cache/distfiles/linux-6.12.114-mykernel/mykernel/config/mykernel-6.12-amd64.config sys-kernel/mykernel-sources/files/

And add this at the end of both ebuilds:

src_prepare() {
	argent-kernel_src_prepare
	cp "${FILESDIR}/mykernel-6.12-amd64.config" "${S}/mykernel/config/" || die
}

From now on, the file in files/ wins over the one in the tarball. Change it there, in both packages. Your overlay uses thin manifests, so it needs no new manifest for it. When the major version changes, the file name in src_prepare() changes too.

Step 5: manifest and install

The manifests are made from your tarball in /var/cache/distfiles. If it isn't there, go back to step 2.

cd /var/db/repos/myoverlay

ebuild sys-kernel/linux-mykernel/linux-mykernel-6.12.114.ebuild manifest

ebuild sys-kernel/mykernel-sources/mykernel-sources-6.12.114.ebuild manifest

epkg install sys-kernel/mykernel-sources

This pulls in linux-mykernel too, and compiles both, there is no binary of your kernel on our binhost. With USE=grub2, the grub menu is regenerated at the end, otherwise run:

grub-mkconfig -o /boot/grub/grub.cfg

And rebuild the external modules (nvidia, virtualbox, zfs, ...) for your kernel:

epkg module-rebuild

Step 6: boot it

Check that the kernel and the initramfs carry your name:

ls /boot/*mykernel*

The list has to include initramfs-genkernel-x86_64-6.12.114-mykernel. If the initramfs is missing, or it says argent, one of the names from Pick a name is wrong.

Reboot, pick your kernel in the GRUB menu, and check:

uname -r

It has to print 6.12.114-mykernel. Our kernel stays installed, so if yours doesn't boot, pick ours in the GRUB menu and fix yours from there.

Step 7: keep it up to date

Your kernel doesn't follow ours. When we move linux-argent to a new version, nothing changes for yours, you decide when to move.

Upgrading the system

With a custom kernel, never upgrade with just epkg upgrade. Always upgrade like this:

epkg update && epkg upgrade --keep-going y && epkg module-rebuild

or, with all the build dependencies too:

epkg update && epkg upgrade-full --keep-going y && epkg module-rebuild

  • epkg update syncs gentoo and argent-ws first
  • --keep-going y: in devmode some packages get compiled, and if one of them fails, portage goes on with the rest instead of stopping the whole upgrade
  • epkg module-rebuild: the external modules on our binhost (nvidia, virtualbox, zfs, ...) are built for our kernel, so when an upgrade brings a new version of one, your kernel doesn't have it until you rebuild it
  • upgrade-full also upgrades the build dependencies (--with-bdeps=y), the packages needed only for compiling, like the ones your kernel and its modules are built with

A new version

  1. Go through step 2 again with the new source, linux-6.12.120-mykernel for example. For the config, start from yours instead of ours: copy /var/cache/distfiles/linux-6.12.114-mykernel/mykernel/config/mykernel-6.12-amd64.config into the new tree as .config, and run make olddefconfig (or make oldconfig, to answer the new options one by one).
  2. Copy your ebuilds to the new version (linux-mykernel-6.12.120.ebuild, mykernel-sources-6.12.120.ebuild), and change K_ROGKERNEL_FORCE_SUBLEVEL.
  3. Make the manifests and install, as in step 5.

Inside the same major version (6.12.x), the new version replaces the old one. A new major version (6.12 to 6.18 for example) installs next to the old one, and there K_ROGKERNEL_FORCE_UPPERLEVEL and the config name change too (mykernel-6.18-amd64.config, also in src_prepare() if you use it). When the new one boots, remove the old one:

epkg remove sys-kernel/linux-mykernel:6.12 sys-kernel/mykernel-sources:6.12

Once the new version works, you can delete the old tree, the old tarball and the old ebuilds.

Changing only the config

Same version, different config. There are two ways.

In the tarball. Change the config in the tree, which is still in /var/cache/distfiles:

cd /var/cache/distfiles/linux-6.12.114-mykernel

cp mykernel/config/mykernel-6.12-amd64.config .config

make menuconfig

cp .config mykernel/config/mykernel-6.12-amd64.config

make mrproper

Pack it again, as in 2.5. The checksums in the manifests don't match the new tarball anymore, so delete both manifests before you make them again, otherwise ebuild ... manifest moves your new tarball aside as a failed download:

cd /var/db/repos/myoverlay

rm sys-kernel/linux-mykernel/Manifest sys-kernel/mykernel-sources/Manifest

Then make them again, as in step 5.

In files/, if you use the optional config next to the ebuilds: change the file in files/ of both packages. No new tarball, no new manifest.

Either way, the version didn't change, and devmode saves every package it compiles in /var/cache/binpkgs, so portage would install the binary it saved last time, with the old config. Rebuild without it:

epkg install --getbinpkg=n --usepkg=n sys-kernel/mykernel-sources sys-kernel/linux-mykernel

After a mode switch

/var/cache/distfiles and /var/db/repos/myoverlay stay as they are. /etc/portage/repos.conf/eselect-repo.conf is gone, put your copy back, otherwise portage doesn't see your overlay anymore.

epkg update syncs only gentoo and argent-ws. Your overlay exists only on your disk, there is nothing to sync.

Removing your kernel

epkg remove sys-kernel/mykernel-sources sys-kernel/linux-mykernel

Because all the names match, this removes your kernel and its initramfs, and leaves ours alone. Without USE=grub2, regenerate the grub menu after it:

grub-mkconfig -o /boot/grub/grub.cfg

TL;DR Oneliners for Experts

avasile --devmode

avasile --status

export MY_CUSTOM_KERNEL_VERSION="6.12"

export MY_CUSTOM_KERNEL_SUBLEVEL="114"

export MY_CUSTOM_KERNEL_FULL_VERSION="${MY_CUSTOM_KERNEL_VERSION}.${MY_CUSTOM_KERNEL_SUBLEVEL}"

epkg fetchsourcepkg =sys-kernel/argent-sources-${MY_CUSTOM_KERNEL_FULL_VERSION}

cd /var/cache/distfiles

tar -xJf linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-argent.tar.xz

mv linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-argent linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel

cd linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel

cp argent/config/argent-${MY_CUSTOM_KERNEL_VERSION}-amd64.config .config

make menuconfig

mkdir -p mykernel/config

cp .config mykernel/config/mykernel-${MY_CUSTOM_KERNEL_VERSION}-amd64.config

rm -rf argent

make mrproper

cd /var/cache/distfiles

tar -pcJf linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel.tar.xz linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel

tar -tJf linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel.tar.xz | head -1

eselect repository create myoverlay

sed -i 's|^masters = .*|masters = gentoo argent-ws|' /var/db/repos/myoverlay/metadata/layout.conf

mkdir -p /var/db/repos/myoverlay/sys-kernel/linux-mykernel /var/db/repos/myoverlay/sys-kernel/mykernel-sources
cat > /var/db/repos/myoverlay/sys-kernel/linux-mykernel/linux-mykernel-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild <<EOF
EAPI=8

K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_REQUIRED_LINUX_FIRMWARE_VER="20260622"
K_ROGKERNEL_FORCE_SUBLEVEL="${MY_CUSTOM_KERNEL_SUBLEVEL}"
K_ROGKERNEL_FORCE_UPPERLEVEL="${MY_CUSTOM_KERNEL_VERSION}"
K_ROGKERNEL_PATCH_UPSTREAM_TARBALL="0"
K_KERNEL_NEW_VERSIONING="1"

inherit argent-kernel

KEYWORDS="amd64"
DESCRIPTION="Custom kernel image"
RESTRICT="mirror"
IUSE="grub2"
EOF

cat > /var/db/repos/myoverlay/sys-kernel/mykernel-sources/mykernel-sources-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild <<EOF
EAPI=8

K_ROGKERNEL_FORCE_SUBLEVEL="${MY_CUSTOM_KERNEL_SUBLEVEL}"
K_ROGKERNEL_FORCE_UPPERLEVEL="${MY_CUSTOM_KERNEL_VERSION}"
K_ROGKERNEL_NAME="mykernel"
K_ROGKERNEL_URI_CONFIG="yes"
K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_ONLY_SOURCES="1"
K_KERNEL_NEW_VERSIONING="1"

inherit argent-kernel

KEYWORDS="amd64"
DESCRIPTION="Custom kernel sources"
RESTRICT="mirror"
IUSE="grub2 sources_standalone"

DEPEND="\${DEPEND}
	sources_standalone? ( !=sys-kernel/linux-mykernel-\${PVR} )
	!sources_standalone? ( =sys-kernel/linux-mykernel-\${PVR} )"
EOF
cd /var/db/repos/myoverlay

ebuild sys-kernel/linux-mykernel/linux-mykernel-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild manifest

ebuild sys-kernel/mykernel-sources/mykernel-sources-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild manifest

epkg install sys-kernel/mykernel-sources

grub-mkconfig -o /boot/grub/grub.cfg

epkg module-rebuild

ls /boot/*mykernel*

reboot

uname -r

epkg update && epkg upgrade --keep-going y && epkg module-rebuild

TL;DR Oneliners for Experts Using TKG kernel source

avasile --devmode

avasile --status

export MY_CUSTOM_KERNEL_VERSION="6.12"

export MY_CUSTOM_KERNEL_SUBLEVEL="114"

export MY_CUSTOM_KERNEL_FULL_VERSION="${MY_CUSTOM_KERNEL_VERSION}.${MY_CUSTOM_KERNEL_SUBLEVEL}"

cd /root

git clone https://github.com/Frogging-Family/linux-tkg.git

cd linux-tkg

sed -i -e 's|^_distro=.*|_distro="Gentoo"|' -e "s|^_version=.*|_version=\"v${MY_CUSTOM_KERNEL_FULL_VERSION}\"|" -e 's|^_configfile=.*|_configfile="running-kernel"|' customization.cfg

./install.sh config

cp -a linux-src-git /var/cache/distfiles/linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel

cd /var/cache/distfiles/linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel

rm -rf .git

make menuconfig

mkdir -p mykernel/config

cp .config mykernel/config/mykernel-${MY_CUSTOM_KERNEL_VERSION}-amd64.config

make mrproper

cd /var/cache/distfiles

tar -pcJf linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel.tar.xz linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel

tar -tJf linux-${MY_CUSTOM_KERNEL_FULL_VERSION}-mykernel.tar.xz | head -1

eselect repository create myoverlay

sed -i 's|^masters = .*|masters = gentoo argent-ws|' /var/db/repos/myoverlay/metadata/layout.conf

mkdir -p /var/db/repos/myoverlay/sys-kernel/linux-mykernel /var/db/repos/myoverlay/sys-kernel/mykernel-sources
cat > /var/db/repos/myoverlay/sys-kernel/linux-mykernel/linux-mykernel-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild <<EOF
EAPI=8

K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_REQUIRED_LINUX_FIRMWARE_VER="20260622"
K_ROGKERNEL_FORCE_SUBLEVEL="${MY_CUSTOM_KERNEL_SUBLEVEL}"
K_ROGKERNEL_FORCE_UPPERLEVEL="${MY_CUSTOM_KERNEL_VERSION}"
K_ROGKERNEL_PATCH_UPSTREAM_TARBALL="0"
K_KERNEL_NEW_VERSIONING="1"

inherit argent-kernel

KEYWORDS="amd64"
DESCRIPTION="Custom kernel image"
RESTRICT="mirror"
IUSE="grub2"
EOF

cat > /var/db/repos/myoverlay/sys-kernel/mykernel-sources/mykernel-sources-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild <<EOF
EAPI=8

K_ROGKERNEL_FORCE_SUBLEVEL="${MY_CUSTOM_KERNEL_SUBLEVEL}"
K_ROGKERNEL_FORCE_UPPERLEVEL="${MY_CUSTOM_KERNEL_VERSION}"
K_ROGKERNEL_NAME="mykernel"
K_ROGKERNEL_URI_CONFIG="yes"
K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_ONLY_SOURCES="1"
K_KERNEL_NEW_VERSIONING="1"

inherit argent-kernel

KEYWORDS="amd64"
DESCRIPTION="Custom kernel sources"
RESTRICT="mirror"
IUSE="grub2 sources_standalone"

DEPEND="\${DEPEND}
	sources_standalone? ( !=sys-kernel/linux-mykernel-\${PVR} )
	!sources_standalone? ( =sys-kernel/linux-mykernel-\${PVR} )"
EOF
cd /var/db/repos/myoverlay

ebuild sys-kernel/linux-mykernel/linux-mykernel-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild manifest

ebuild sys-kernel/mykernel-sources/mykernel-sources-${MY_CUSTOM_KERNEL_FULL_VERSION}.ebuild manifest

epkg install sys-kernel/mykernel-sources

grub-mkconfig -o /boot/grub/grub.cfg

epkg module-rebuild

ls /boot/*mykernel*

reboot

uname -r

epkg update && epkg upgrade --keep-going y && epkg module-rebuild

All the steps above, in both TL;DR sections, are done only once. After that, maintaining your custom kernel means:

  1. Archiving the new version of the kernel: the new tree with your config, packed as linux-6.12.120-mykernel.tar.xz in /var/cache/distfiles
  2. Copying the ebuilds to the new version
  3. Changing the versions of the kernel in the new ebuilds (K_ROGKERNEL_FORCE_SUBLEVEL, and K_ROGKERNEL_FORCE_UPPERLEVEL for a new major version)