Rebuild Linux Module Dependencies Safely with depmod

You installed a driver, and modprobe cannot find it or its dependencies. Rebuilding the index with depmod usually fixes that. This guide rebuilds the dependency and symbol indexes for one installed kernel, verifies what changed, and covers staging trees and configuration files. The examples match kmod 31 and take about 10 minutes if the module tree is healthy.

You need a shell account, the target kernel's module directory, and sudo for the final write.

Before you start

depmod reads kernel modules from /lib/modules/VERSION by default, where VERSION is the running kernel from uname -r. With no file names, it probes all modules. It does not load or unload a module; it creates metadata used later by tools such as modprobe.

Check the executable and the target directory first:

$ depmod --version
kmod version 31
$ KVER=$(uname -r)
$ printf 'kernel: %s\n' "$KVER"
kernel: 6.8.0-139-generic
$ test -d "/lib/modules/$KVER" && echo 'module tree exists'
module tree exists

Your kernel version will differ. If the directory is missing, stop here. Installing or copying modules is a separate job, and running depmod cannot create a useful index for files that are not present.

1. Preview the dependency data

Use the dry-run form before changing a live tree. The -n option sends the generated dependency and map data to standard output instead of writing the module directory. Limit the display while investigating, because a complete index can be large:

$ KVER=$(uname -r)
$ depmod -n "$KVER" | sed -n '1,8p'
kernel/arch/x86/events/amd/amd-uncore.ko.zst:
kernel/arch/x86/events/intel/intel-cstate.ko.zst:
kernel/arch/x86/events/rapl/rapl.ko.zst:
kernel/arch/x86/kernel/cpu/mce/mce-inject.ko.zst:
kernel/arch/x86/kernel/msr.ko.zst:
kernel/arch/x86/kernel/cpuid.ko.zst:
kernel/arch/x86/crypto/twofish-x86_64.ko.zst: kernel/crypto/twofish_common.ko.zst

Checkpoint: each line names a module followed by the modules it needs. A line ending at the colon has no recorded dependency. The exact list depends on your kernel package, compression format and installed drivers, so compare structure rather than copying these names.

2. Rebuild the live index

When the preview is sensible, rebuild the index for the chosen kernel:

$ sudo depmod "$KVER"
$ printf 'depmod exit status: %s\n' "$?"
depmod exit status: 0

This writes files such as modules.dep, modules.dep.bin, modules.symbols, modules.symbols.bin and, when applicable, modules.devname under /lib/modules/$KVER. The binary index is the one kmod tools use. The text file is for human reading only, and its format is not a stable interface.

Warning: this is a state-changing command. It does not insert a module or restart a service, but it can still affect the next module load, so run it during a maintenance window if you are repairing a driver on a production host.

Recovery: restore the index files from your package or system backup, then run the package's normal module post-install step. Do not hand-edit modules.dep.

3. Make repeated rebuilds cheap

The -A or --quick option checks whether any module is newer than modules.dep. If nothing is newer, it exits silently without regenerating the files:

$ sudo depmod --quick "$KVER"
$ printf 'quick check status: %s\n' "$?"
quick check status: 0

Tip: silence means that no rebuild was needed, not that the directory was inspected successfully in every way. Use the ordinary command when you have replaced indexes, changed depmod configuration, or want an unambiguous regeneration.

4. Use a staging tree without contaminating the host

Distribution and image builders can generate metadata before the files are installed. With -b, depmod prepends a staging root to the normal module path and strips that root from paths recorded in the result. The expected layout is:

$ STAGE=/path/to/staging-root
$ KVER=TARGET_KERNEL_VERSION
$ find "$STAGE/lib/modules/$KVER" -maxdepth 1 -type d -print
/path/to/staging-root/lib/modules/TARGET_KERNEL_VERSION
$ depmod -b "$STAGE" -n "$KVER" | sed -n '1,5p'

Replace both placeholders with a real build directory and kernel version. The dry run keeps this example non-destructive. To write the staged index, remove -n after checking the input tree.

Tip: if the image uses a different module prefix, kmod 31 also supports -m, and -o selects a separate output root. Read the interaction carefully before combining these options: output precedence can make the input and output trees differ.

5. Control which duplicate module wins

Files in /lib/depmod.d, /usr/lib/depmod.d, /usr/local/lib/depmod.d, /run/depmod.d and /etc/depmod.d can alter processing order. Files are read as simple commands, with blank lines and comments ignored. A trailing backslash continues a line.

For example, a configuration file can give an external module directory priority:

# /etc/depmod.d/90-local-modules.conf
external * /opt/vendor/lib/modules
search external updates built-in

Configuration changes do nothing until you regenerate the relevant index. Preview with depmod -n, then rebuild. If you need a one-off configuration location, -C FILE_OR_DIRECTORY replaces the default configuration lookup. Keep locally managed files separate from package-owned files so an upgrade does not erase your decision.

6. Diagnose unresolved symbols

Missing symbols usually point to a module built for the wrong kernel, an incomplete install, or a third-party driver that was not built against the matching kernel. The -e check reports unresolved symbols only when paired with either -F System.map or -E Module.symvers. Those options are mutually exclusive:

$ sudo depmod -e -F /path/to/System.map "$KVER"
$ printf 'symbol check status: %s\n' "$?"
symbol check status: 0

Use the System.map produced for the same kernel build. Use -E instead when you have that build's Module.symvers.

Warning: a non-zero result or an unresolved-symbol line is a diagnostic signal, not a reason to force the module into the kernel. Check the module's build logs and kernel version first.

Common traps

Done means