Custom lightweight kernel

What's the most efficient way to configure a minimal kernel? Instead of copying GENERIC and going over it with a fine-tooth comb, can I just vi MYKERNEL and include GENERIC then define my settings so that they override the GENERIC settings? Also, given this will be my first custom FreeBSD kernel, what's the bare necessities for a server and can I still get away with the quick procedure [*]?

[*]
Code:
# cd /usr/src
# make buildworld
# make buildkernel installkernel KERNCONF=MYKERNEL
# make installworld
# mergemaster -Ui
# shutdown -r now
 
There is no efficient way. A minimal kernel is tailored to the hardware and what it's used for. This tailoring takes time and experience.

Start by making a backup of /boot/kernel/ (e.g. copy it to /boot/generic/). While chipping away stuff from your kernel config you will end up with a kernel that won't boot. Having a known-good kernel around allows you to get the machine back up ( make installkernel creates a backup of the last kernel in /boot/kernel.old/ but if you run it twice without rebooting in between - and it will happen, trust me - you risk bricking the machine).

The next step is to create a copy of GENERIC. Experience shows that you don't want to keep your custom kernel config(5) under /usr/src/. Instead keep it in, for example, /root/kernels/ and symlink it to /usr/src/sys/$ARCH/conf/.

Once you have copied GENERIC start removing all the devices you don't have/need. kldstat(), dmesg(), pciconf(), devinfo() and common sense are your friends. A nice trick to speed up make buildkernel is setting MODULES_OVERRIDE in /etc/make.conf. This variable defines which modules will be build (instead of "all of them"). Be careful when using it.

Removing options from the kernel configuration is the most error-prone part of creating a minimum kernel. There are many dependencies that aren't documented anywhere. Chances are that other people already figured things out, so feed any error messages returned by make buildworld to a search engine.

Note that your "quick procedure" will get you in trouble sooner or later. I works most of the time, except when it doesn't. See less -p "General Notes" /usr/src/UPDATING.

HTH... Good luck! :)
 
worldi said:
Once you have copied GENERIC start removing all the devices you don't have/need.

This is how I used to create a custom kernel, but the problem is that you have to keep track of changes to GENERIC so if a new option or device is added that you care about, you can add that to your custom kernel. This problem and its solution (including GENERIC and overriding options as desired) is addressed by @wblock in one of his helpful articles.
 
Last edited by a moderator:
cbunn said:
[...] so if a new option or device is added that you care about, you can add that to your custom kernel.

The "include GENERIC path" is definitely the way to go when you just want to turn on/off a few options/devices. However, if you're after a truly minimal configuration then it's counterproductive: every time GENERIC changes you have to take a look at it because it's very likely that something was added that you do not care about. It is also harder to figure out what the resulting configuration actually includes because you now have two files to look at.
 
worldi said:
There is no efficient way. A minimal kernel is tailored to the hardware and what it's used for. This tailoring takes time and experience.

Start by making a backup of /boot/kernel/ (e.g. copy it to /boot/generic/). While chipping away stuff from your kernel config you will end up with a kernel that won't boot. Having a known-good kernel around allows you to get the machine back up ( make installkernel creates a backup of the last kernel in /boot/kernel.old/ but if you run it twice without rebooting in between - and it will happen, trust me - you risk bricking the machine).

The next step is to create a copy of GENERIC. Experience shows that you don't want to keep your custom kernel config(5) under /usr/src/. Instead keep it in, for example, /root/kernels/ and symlink it to /usr/src/sys/$ARCH/conf/.

Once you have copied GENERIC start removing all the devices you don't have/need. kldstat(), dmesg(), pciconf(), devinfo() and common sense are your friends. A nice trick to speed up make buildkernel is setting MODULES_OVERRIDE in /etc/make.conf. This variable defines which modules will be build (instead of "all of them"). Be careful when using it.

Removing options from the kernel config is the most error-prone part of creating a minimum kernel. There are many dependencies that aren't documented anywhere. Chances are that other people already figured things out, so feed any error messages returned by make buildworld to a search engine.

Note that your "quick procedure" will get you in trouble sooner or later. I works most of the time, except when it doesn't. See less -p "General Notes" /usr/src/UPDATING.

HTH... Good luck! :)

Thanks, @worldi. That certainly helped and I successfuly built and installed my new kernel. I'm having problems with installing the new world, though; I think I might have run into some problems from the quick procedure. See below.

cbunn said:
worldi said:
Once you have copied GENERIC start removing all the devices you don't have/need.

This is how I used to create a custom kernel, but the problem is that you have to keep track of changes to GENERIC so if a new option or device is added that you care about, you can add that to your custom kernel. This problem and its solution (including GENERIC and overriding options as desired) is addressed by @wblock in one of his helpful articles.

Thanks for that link, @cbunn.

Like I said, I've managed to make buildkernel installkernel KERNCONF=PERNELL; however, I didn't reboot into single user mode. Instead, I immediately ran make installworld, which resulted in this:

Code:
root@nakatomi:/usr/src # make installworld
ERROR: Required unbound user is missing, see /usr/src/UPDATING.
*** Error code 1

Stop.
make[1]: stopped in /usr/src
*** Error code 1

Stop.
make: stopped in /usr/src
root@nakatomi:/usr/src # grep unbound /etc/passwd
unbound:*:59:59:Unbound DNS Resolver:/var/unbound:/usr/sbin/nologin
root@nakatomi:/usr/src #

I don't know if this will be rectified by booting into single user mode and running mergemaster -p because as you can see, the user does indeed exist [*]!

What should I do?

[*] /usr/src/UPDATING
Code:
20130916:
        With the addition of unbound(8), a new unbound user is now
        required during installworld.  "mergemaster -p" can be used to
        add the user prior to installworld, as documented in the handbook.
 
Last edited by a moderator:
Your password database might be out of sync with your passwd file. That happens sometimes. The easiest way to fix it is to run vipw, quit and save. The database should be rebuilt after that and the unbound user should really exist.
 
I just:

Code:
# vipw
:wq

which was good enough. I would never have figured that one out, though. Thanks again.
 
@SirDice, I'm not sure of the right sequence for this part. Do I:

portmaster -f
make delete-old-libs

or

make delete-old-libs
portmaster -f

Also, if the first option, do I portmaster -f inside each jail before deleting old libraries? Thanks.
 
Last edited by a moderator:
Back
Top