In modern Linux server administration and DevOps infrastructure on Ubuntu, specific hardware accelerators, virtualization drivers, and container networking subsystems require kernel modules to be resident in memory before dependent daemons initialise. While the dynamic device manager systemd-udevd automatically loads drivers in response to hotplug hardware uevents, software-defined kernel facilities—such as Docker and Kubernetes overlay storage (overlay), bridge packet filtering (br_netfilter), WireGuard cryptographic tunneling (wireguard), or KVM virtualization (kvm_intel)—do not emit hardware bus signals. To ensure these kernel modules load reliably and statically at early boot, Ubuntu provides the systemd-modules-load.service daemon. This service parses declarative configuration files located within the /etc/modules-load.d/ directory hierarchy.
Understanding systemd-modules-load Architecture and Configuration Paths
The systemd-modules-load daemon executes during the early boot phase, well before standard network interfaces or user-space containers start. It parses configuration files across three distinct system directories in strictly defined precedence order:
/etc/modules-load.d/*.conf: Local administrator configurations. Files placed here have the highest priority and override vendor files of the same name./run/modules-load.d/*.conf: Runtime transient configurations generated by installer scripts, cloud-init, or early-boot generators./usr/lib/modules-load.d/*.conf: Upstream distribution defaults shipped by Ubuntu packages. Administrators should avoid editing these files directly, as package upgrades will overwrite changes.- Legacy File: For backwards compatibility with Debian legacy sysvinit configurations,
systemd-modules-loadalso reads/etc/modules. However, modern systemd administration recommends using modular drop-ins in/etc/modules-load.d/.
Inspecting Active Kernel Module Loading Service State
To verify the operational status of the module loader service in Ubuntu, query its systemd unit:
systemctl status systemd-modules-load.service
To view all modules successfully loaded by the service during the current boot cycle, query the systemd journal:
journalctl -u systemd-modules-load.service --no-pager
The log output demonstrates the sequence of parsed files and confirmed module insertions:
systemd[1]: Starting Load Kernel Modules...
systemd-modules-load[412]: Inserted module 'overlay'
systemd-modules-load[412]: Inserted module 'br_netfilter'
systemd[1]: Finished Load Kernel Modules.
Creating Declarative Module Drop-Ins in /etc/modules-load.d/
Configuration files in /etc/modules-load.d/ are simple plaintext files containing lists of module names separated by newlines. Empty lines and lines starting with # or ; are treated as comments.
Example 1: Preparing Host for Containerization (Docker and Kubernetes)
Container engines require overlay filesystems and bridge netfilter modules loaded before daemon startup. Create a dedicated drop-in file:
sudo bash -c 'cat <<EOF > /etc/modules-load.d/container-runtime.conf
# Enable container filesystem overlay driver
overlay
# Enable bridge netfilter for iptables packet inspection
br_netfilter
EOF'
Example 2: Enabling Cryptographic Accelerators and IPsec Networking
For high-throughput VPN gateways or database servers:
sudo bash -c 'cat <<EOF > /etc/modules-load.d/vpn-cryptography.conf
# Hardware-accelerated AES encryption
aesni_intel
# Kernel crypto user-space API
crypto_user
# WireGuard secure network tunnel
wireguard
EOF'
Testing and Applying Module Loading Without Rebooting
Rather than rebooting the machine to verify newly created configuration files, administrators can trigger systemd-modules-load manually:
# Restart the service to immediately load newly configured modules
sudo systemctl restart systemd-modules-load.service
# Verify service exit status
systemctl is-active systemd-modules-load.service
You can also execute the binary directly to test configuration syntax and inspect verbose debugging output:
sudo /lib/systemd/systemd-modules-load
Verifying Loaded Modules in the Running Kernel
To confirm that the kernel has accepted and linked the modules into memory, query lsmod or check /proc/modules:
# Check if overlay and br_netfilter are active in kernel memory
lsmod | grep -E 'overlay|br_netfilter'
A typical output confirms memory size and dependent subsystems:
overlay 155648 12
br_netfilter 32768 0
bridge 311296 1 br_netfilter
Configuring Module Parameters in /etc/modprobe.d/
While /etc/modules-load.d/ defines which modules to load at boot, it does not accept runtime module parameters (such as buffer sizes or debug flags). If a module requires specific hardware options, configure them in parallel within /etc/modprobe.d/:
# Define runtime parameters for the KVM kernel module
sudo bash -c 'cat <<EOF > /etc/modprobe.d/kvm-intel.conf
options kvm_intel nested=1
options kvm_intel enable_shadow_vmcs=1
EOF'
When systemd-modules-load loads kvm_intel, the kernel automatically references /etc/modprobe.d/kvm-intel.conf to apply the nested virtualization parameters.
Troubleshooting Module Loading Failures
If a module fails to load (for example, if the module is missing from the active kernel build or conflicts with hardware capabilities), systemd-modules-load logs the exact kernel error to the journal:
# Inspect recent failures
journalctl -u systemd-modules-load.service -p err
If a module is obsolete or blacklisted, remove its entry from /etc/modules-load.d/*.conf to maintain a pristine, zero-error boot sequence.
By leveraging systemd-modules-load and modular drop-in configurations, Ubuntu system administrators establish reproducible, deterministic kernel module configurations, ensuring that critical virtualization, networking, and security subsystems initialize flawlessly across enterprise infrastructure.