But why?

You want to build a custom kernel to enable experimental hardware or features or outdated hardware, to reduce bloat further, to tune the kernel to the hardware.

The vanilla kernel for most Alpine ARCHs uses defaults to balance throughput at the expense of some responsiveness, and support for many devices. You can tweak the kernel for desktop use and low latency and responsiveness.

You should disable modules to increase security. By default, Alpine will install modules but not disable most of them. Disabling modules will reduce an DMA attack but not eliminate it completely. If you have a newer processor with VT-d, you can mitigate as long as you:

Leave CONFIG_INTEL_IOMMU_DEFAULT_ON=y or pass intel_iommu=on as a kernel parameter and disable kernel logging so the attacker doesn't gain DMAR address information through dmesg.[1] Also remove references to the kernel version to calculate the IOMMU addresses.[2]

To increase the security of the boot process, if you have a TPM, you could set CONFIG_INTEL_TXT=y (Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)) (which is not enabled in the hardened kernel by default), then you would need the SINIT module (provided only by Intel)[3], a possibly compiled TrustedGrub2[4], trousers[5], tboot[6]. These packages are not in aports and it is unknown if these tools work on musl. It's not recommended for Edge. Also, there would be trigger packages to generate hashes for the kernel and the mkinitfs updates.

Working with aports

We will try using an existing vanilla kernel just tweaking the configure-vanilla.ARCH file.

You can use linux-hardened but it is being deprecated or phased out. grsecurity is the biggest patch added but its support released to the open-source community as in new updates ended.

Switching to the proper release version

You need to switch to the proper branch that matches the release so that the kernel compiles against the dependencies properly.

Alpine version

Remote branch

Edge

master

3.7.0

3.7-stable

The following is required to get access to the APKBUILD released for that version of Alpine and which you will create a commit for.

If you are on 3.7 do:

git checkout -b 3.7-stable origin/3.7-stable

If you are on Edge do:

git checkout master

Creating your config

You can use linux-vanilla but what you should do is create a local branch by doing:

For Alpine Edge:

git checkout -b my-custom-kernel

For Alpine 3.7:

git checkout -b my-custom-kernel origin/3.7-stable

Doing it this way, you do less work in maintaining. All you need to do is keep master or 3.7-stable in sync[7][8] and merge any conflicts.

First switch to the branch by doing git checkout my-custom-kernel. Then, you need to navigate to the main/linux-vanilla folder where you should see a APKBUILD and some config- files. When you are done with your edits either by editing directly the APKBUILD and copying the config-vanilla.ARCH as .config in the linux-4.15 folder. You will then move the .config back overriding the config-vanilla.ARCH generated by make menuconfig (discussed below in the Configuring kernel section). After generating your config, you need to abuild checksum. Then, do git add APKBUILD config-vanilla.ARCH where ARCH is whatever architecture (x86, x86_64, ...) you use. Then, you need to do git commit APKBUILD config-NAME.ARCH -m "Enabled these options ...." for your customization the ARCHitecture of your system. You do this so that git can keep your code separate from Alpine's and so your changes float forward between kernel updates.

Adding custom patches

Custom patches should be added to sources=.

After you added the URL, you need to produce a checksum by doing abuild checksum.

The custom patches may not be autopatched, due to being distributed as an archive or different patch level, so you need to define what to do with it in the prepare().

Configuring kernel

Attempt to build the kernel first. To do that, you do abuild -rK to install most of the dependencies. If it complains about a dependency like elfutils-dev use -rKd. Then, when it prompts for values for new found config options just hold enter till it starts compiling the kernel. There should be two sets one for -vanilla and the other for the -virt. Just Ctrl+C out of the compilation process after the second set so you can further customize the config. Then you go into the src/linux-VER and edit the config file. Copy the .config file overriding the config-NAME.ARCH in the srcdir.

The alternative is to use the kernel configuration menu in the build-NAME folder, but before yo do that you need to sudo apk add ncurses-dev

After you are done using the menu in the build-NAME folder by doing make menuconfig, you want to remove ncurses-dev. When you are done, it will be stored in .config which you need to again override the config-NAME.ARCH file. When you are done updating the config-NAME.ARCH, you need to do abuild checksum.

The options in the kernel config are typically defaults. If your device is old, it may be set to n by default.

Either -march=armv7-a or -march=armv5t -Wa,-march=armv7-a based on a compile test. -mfpu=vfp

100 Hz

Voluntary Kernel Preemption (Desktop)

32

aarch64

Allwinner sunxi 64-bit SoC Family

Broadcom BCM2835 family

Marvell Berlin SoC Family

ARMv8 based Samsung Exynos SoC family

ARMv8 based Freescale Layerscape SoC family

Hisilicon SoC Family

Mediatek MT65xx & MT81xx ARMv8 SoC

Marvell EBU SoC Family

Qualcomm Platforms

Rockchip Platforms

AMD Seattle SoC Family

Altera's Stratix 10 SoCFPGA Family

NVIDIA Tegra SoC Family

Spreadtrum SoC platform

Cavium Inc. Thunder SoC Family

ARMv8 software model (Versatile Express)

AppliedMicro X-Gene SOC Family

Xilinx ZynqMP Family

300 HZ

Voluntary Kernel Preemption (Desktop)

64

If you do desktop multitasking, you may want to switch to Voluntary Kernel Preemption (Desktop) or Preemptible Kernel (Low-Latency Desktop) and up the Timer Frequency. If you run a dedicated render farm node or a dedicated bitcoin miner use No Forced Preemption (Server) and decrease the Timer Frequency.

Optimized modules (most are already compiled as modules):

raid6 -- altivec, avx512, ssse3, avx2, mmx, sse, sse2, neon

some operations of raid5 -- mmx (32 bit), sse (64 bit), avx

For Kernel API:

32-bit memcpy -- 3dnow

32-bit memory page clearing and copying -- sse (Athlon/K7 only), mmx

From x86/crypto, arm/crypto, powerpc/crypto:

CAMELLIA -- avx2, avx, aes-ni

CHACHA20 -- avx2, neon

CAST5 -- avx

CAST6 -- avx

TWOFISH -- avx

SERPENT -- avx2, avx, sse2

SHA1 -- avx2, ssse3, neon, spe

SHA2 -- avx2

SHA256 -- ssse3, neon, spe

SHA512 -- avx2, ssse3, neon

POLY1305 -- avx2

GHASH -- pclmulqdq (part of aes-ni), vmx (power8)

AES -- aes-ni, neon, vmx (power8), spe

CRC32 -- pclmulqdq, sse, neon, vmx (power8)

CRCT10DIF -- pclmulqdq, sse, neon, vmx (power8)

Fast reboots with kexec

If you want to reboot the kernel fast avoiding the POST test, you need sudo apk add kexec-tools and enable kexec in the kernel:

Processor type and features
[*] kexec system call

Hibernation to prevent data loss

Hibernation should be used if you have a laptop. You don't want the laptop to suddenly shut off resulting in data loss, you want it to save your work based on a percentage of battery life (this requires special script). When you do hibernation and when it restores back, it should lock down the computer and ask for prompt. Depending on your needs, the hibernated image can be encrypted/decrypted which again requires additional customization to scripts.

Hibernation with an unsanitized swap file is generally insecure because data and unlocked memory pages is swapped out in plaintext. To increase the security either disable swap (Alpine default) or use an encrypted swap. The swap file/partition is typically used as a dump of the hibernated image.

Building

Before building, you may want to remove much modules as possible. This will reduce the time to compile greatly. Also, you may want to use ccache for faster recompiles especially if you are searching for the minimal set of options or modules to use or include.

You should then do an abuild -r to attempt to build it.

Installing

To install it you do a sudo apk add linux-NAME where NAME is vanilla or hardened.

Testing

Before you test, you should install the other kernel, so if you use vanilla, then you should sudo apk add linux-hardened and vice versa. You may be missing a module and can't boot, so you use the other kernel as the fallback boot kernel. Don't forget to update your bootloader configuration.

To test, first you should make a bootable Alpine USB image. Then, when you have your rescue USB done, you sudo reboot the computer.

To test it, you basically do trial and error. Sometimes your config is missing something if you want to have a bare minimum setting.

If you are curious about correctness testing, some kernel modules or components do preform self tests at the beginning of the boot process. The tools may have test suites that you run with the make command.