1. Introduction

In Linux, kernel modules are a method for extending the functionality of the kernel without replacing, configuring, or recompiling code. Although they are meant to be dynamically pluggable, knowing how to ensure a given module loads on startup can help avoid repetition and manual setup.

In this tutorial, we explain how modules can get loaded during the boot procedures and how we can automate that process. First, we go over ways to load modules automatically when the system starts. After that, we explore how to perform additional operations and use more features of the module loading system during boot.

We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments unless otherwise specified.

2. Kernel Module Loading at Boot

Many Linux distributions have configuration options that enable the automatic loading of kernel modules when the system boots.

2.1. /etc/modules

Before Linux kernel version 2.6, the /etc/modules file contained a newline-separated list of module names to load during boot:

$ cat /etc/modules
modulename1
modulename2

Here, the precedence is by line.

However, since kernel version 2.6, many distributions have added more options for module loading.

2.2. systemd-modules-load

In fact, a standard and fairly universal method to ensure a given kernel module loads on its own involves the systemd-modules-load service as part of the systemd initialization management. After ensuring the service is started with systemctl, we can perform the necessary setup:

$ systmctl start systemd-modules-load

Two kernel boot parameter relate to this service: modules_load and rd.modules_load. Both take a comma-separated list of modules to load, but the latter only acts with initrd

In addition, *systemd-modules-load provides several directories for [*.conf]iguration files**:

  • /etc/modules-load.d/
  • /run/modules-load.d/
  • /usr/lib/modules-load.d/
  • /usr/local/lib/modules-load.d/

A .conf file usually accounts for a single module, in which case the convention is to use the name of that module as the filename. On the other hand, groups of modules can be loaded with a single configuration file as well.

Regardless, a .conf file is just a list of kernel module names, one per line, with line comments using an # octothorp or ; semicolon:

$ cat /etc/modules-load.d/cups-filters.conf
# Parallel printer driver modules loading for cups
# LOAD_LP_MODULE was 'yes' in /etc/default/cups
lp
ppdev
parport_pc

Here, we use cat to output the contents of /etc/modules-load.d/cups-filters.conf, responsible for loading three kernel modules, associated with the Common Unix Printing System (CUPS).

Notably, both of the solutions above only enable module loading without any additional options or extra features.

3. Kernel Module Boot Operations Automation and modprobe.d

To load and unload modules, Linux systems use the modprobe tool from the kmod package:

$ modprobe modulename

Yet, we can also employ the modprobe.d directory available at several possible locations:

  • /etc/modprobe.d/
  • /run/modprobe.d/
  • /lib/modprobe.d/
  • /usr/lib/modprobe.d/
  • /usr/local/lib/modprobe.d/

The modprobe.d directories should contain .conf files with modprobe command parameters and arguments on separate lines. Thus, unlike the contents of files in modules-load.d, modprobe.d configurations can perform most actions that modprobe can. Adding the necessary commands to any modprobe.d .conf file ensures their execution on boot.

Officially, the /etc/modprobe.conf file can still combine all of these configurations in one place. However, /etc/modprobe.conf is due for deprecation.

Finally, problems with modules might arise due to an incorrect configuration or environment.

3.1. Priority

Since the order of execution for some commands and options is important, files in modprobe.d can have filenames that begin with their priority, as we see via ls:

$ ls /etc/modprobe.d/
50-alsa-base.conf
10-modem.conf

However, that’s not a strict rule. In fact, only some Linux distributions follow the convention. Yet, the loading order among files in modprobe.d can be assumed to follow the regular sorting of filenames.

Still, we can group commands within the same configuration:

$ cat /etc/modprobe.d/51-audio.conf
softdep sound pre: alsa-base post: 
install xostaudio

Here, we combine two commands that relate to audio within the same file.

3.2. Commands

Further, each modprobe.d file command has its precedence. In fact, we can list all commands in the order of their processing:

  1. alias
  2. blacklist
  3. softdep
  4. install
  5. remove
  6. options

To show the current configuration, we use the –showconfig or -c flag of modprobe:

$ modprobe --showconfig
blacklist amodule
blacklist bmodule
[...]
install module1 modprobe module1; sleep 5; echo "Loaded module1"
remove module2
options module1 opt=val arg=vae
softdep module1 pre: module2 post: module3
[...]
# End of configuration files. Dumping indexes now:

alias amodule amo
alias bmodule bmo
alias module1 mod1
alias module2 mod2
[...]

Let’s continue with the possible commands within modprobe.d configuration files.

3.3. alias

To begin with, we use alias to introduce module aliases for convenience:

$ cat /etc/modprobe.d/aliases.conf
alias modx module_of_x

At this point, we can refer to module_of_x as just modx. So, any other commands that need to specify module_of_x, can use either name.

3.4. blacklist

True to its name, the blacklist command prevents the loading of a given module and its aliases. Since it takes precedence over all other commands, we can be sure that its presence blocks related calls:

$ cat /etc/modprobe.d/denied.conf
blacklist module1
blacklist module2

Moreover, we can instead use module_blacklist or the more recent modprobe.blacklist kernel boot parameter and assign it a comma-separated list of module names:

$ cat /proc/cmdline
[...] modprobe.blacklist=module1,module2

This way, we prevent each module in the list from being loaded even before the kernel boot stage, when the bootloader is in control.

3.5. install and remove

The function of both install and remove is to invoke a specific command or shell script instead of performing the respective load or unload operation:

$ cat /etc/modprobe.d/module1.conf
install module1 modprobe module1; sleep 5; echo "Loaded module1." > /var/log/module1.log
$ cat /var/log/module1.log
cat: /var/log/module1.log: No such file or directory
$ modprobe module1
$ cat /var/log/module1.log
Loaded module1.

In this case, we see several semicolon-separated shell commands following the install keyword and the module name module1 in /etc/modprobe.d/module1.conf. The last command rewrites the /var/log/module1.log file with the content Loaded module1. After using modprobe to (still) manually load the module, we see the previously non-existent /var/log/module1.log appears. So, we only introduce a small 5-second delay with sleep before declaring the module as loaded.

Had we used remove, the trigger would have been modprobe -r module1, i.e., the unloading of module1.

3.6. options

The options command enables us to add options or parameters to a module:

$ cat /etc/modprobe.d/module1.conf
options module1 var=val

In this case, we add the var parameter and assign it the value val. Thus, we can include necessary customization according to our needs and what the module supports.

3.7. softdep

Finally, we can add optional dependencies that a module might request using softdep:

$ cat /etc/modprobe.d/module1.conf
softdep module1 pre: module2 post: module3

Here, we try to load module2 before module1 using pre:. On the other hand, post: attempts to ensure module3 is loaded after loading module1. While they’re not hard requirements, lacking any soft dependencies might result in reduced functionality.

4. Summary

In this article, we looked at ways to load kernel modules on boot and automate modprobe.

In conclusion, due to its flexibility and versatility, Linux usually loads modules as they are needed instead of preemptively, so automating this process at boot should rarely be needed. Still, should we need to do so, there are several automatic kernel module loading options at our disposal.