# Custom lightweight kernel



## nanotek (Feb 2, 2014)

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 [*]?

[*]
	
	



```
# cd /usr/src
# make buildworld
# make buildkernel installkernel KERNCONF=MYKERNEL
# make installworld
# mergemaster -Ui
# shutdown -r now
```


----------



## worldi (Feb 2, 2014)

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!


----------



## cbunn (Feb 2, 2014)

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.


----------



## worldi (Feb 2, 2014)

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.


----------



## nanotek (Feb 3, 2014)

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).
> 
> ...



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:
> 
> 
> 
> ...



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:


```
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

```
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.
```


----------



## SirDice (Feb 3, 2014)

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.


----------



## nanotek (Feb 3, 2014)

@SirDice, you're a genius! It worked. Thank you


----------



## SirDice (Feb 3, 2014)

It can also be done with the pwd_mkdb(8) tool (it's run after you quit vipw(8)) but I can never remember the correct syntax.


----------



## nanotek (Feb 3, 2014)

I just:


```
# vipw
:wq
```

which was good enough. I would never have figured that one out, though. Thanks again.


----------



## nanotek (Feb 3, 2014)

@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.


----------

