DKMS(8)

๐Ÿ’– DKMS ๐Ÿ’–

okay bestie, welcome to the dkms (that's Dynamic Kernel Module Support) manual page โ€” it lives in the System Manager's Manual section (8), and it's about to be your new hyperfixation. grab a boba, we're doing this ๐Ÿง‹โœจ


โœจ SYNOPSIS โœจ

dkms [action] [options] [module/module-version] [/path/to/source-tree]
     [/path/to/tarball.tar] [/path/to/driver.rpm]

that's the whole vibe check right there โ€” action, options, a module, and maybe a path to something ๐Ÿซถ


๐ŸŒธ DESCRIPTION ๐ŸŒธ

so basically, dkms is a framework that lets kernel modules get dynamically built for every kernel on your system โ€” in a simplified and organized fashion. no cap. it's the organized bestie of kernel module management, and honestly? iconic. ๐Ÿ’…


๐ŸŽ€ ACTIONS ๐ŸŽ€

each action is its own little main character moment. here we go ๐Ÿ‘‘


add

add [module/module-version|/path/to/source-tree|/path/to/tarball.tar]
  • this one adds a module/module-version combo to the tree so it can be built and installed later ๐Ÿ’–
  • if you pass module/module-version, -m module/module-version, or -m module -v module-version as options, then this command needs source sitting in /usr/src/<module>-<module-version>/ plus a properly formatted dkms.conf file. both. it's a package deal fr fr
  • if you pass /path/to/source-tree as an option, and that source-tree contains a dkms.conf file, it'll copy /path/to/source-tree over to /usr/src/module-module-version โœจ
  • if you pass /path/to/tarball.tar, this command behaves like the ldtarball command. plot twist, but make it convenient ๐Ÿฆ‹

remove

remove [module/module-version] [-k kernel/arch] [--all]
  • removes a module/version or a module/version/kernel/arch combination from the tree ๐Ÿงน
  • if the module is currently installed, it uninstalls it first, and if applicable, replaces it with its original_module. so polite of it honestly
  • use the --all option if you want to remove all instances for every kernel at once. go big or go home ๐Ÿ’€

build

build [module/module-version] [-k kernel/arch] [--force]
  • builds the specified module/version combo for the specified kernel/arch ๐Ÿ”จ
  • no -k option? then it builds for the currently running kernel and arch. default behavior, love that for you
  • all builds happen in the directory /var/lib/dkms/<module>/<module-version>/build/ โ€” that's the build zone ๐Ÿ 
  • if the module/module-version combo hasn't been added yet, dkms will try to add it โ€” which means build can take the same arguments that add can. multitasking queen ๐Ÿ‘‘
  • if the module is already built, it will not be rebuilt again by default. if you want to force it, that's what --force is for โšก

unbuild

unbuild [module/module-version] [-k kernel/arch] [--all]
  • undoes the build for a module/version or module/version/kernel/arch combination from the tree โ†ฉ๏ธ
  • if the module is currently installed, it uninstalls it first, and if applicable, replaces it with its original_module. then, finally, all binary kernel modules get removed ๐Ÿซก
  • use --all to remove all instances for every kernel at once. same energy as remove --all, different day ๐ŸŒˆ

install

install [module/module-version] [-k kernel/arch] [--force]
        [/path/to/driver.rpm]
  • installs a built module/version combo onto the kernel it was built for ๐Ÿ’–
  • no kernel option? it assumes the currently running kernel. assumptions are made, respectfully
  • module not built yet? dkms will try to build it. module not added yet? dkms will try to add it. and in both of those cases, the install command can take the same arguments as the build or add commands. it's giving "we contain multitudes" โœจ
  • already installed? it will not be reinstalled again by default โ€” --force overrides that ๐Ÿšจ
  • if a different version of the module is installed for that kernel, it gets uninstalled first, so that none of its kernel modules are left behind. no crumbs. periodt ๐Ÿงน
  • if you pass a .rpm file, dkms will try to install that file with rpm -Uvh, and it will perform an autoinstall action to make sure everything is built for your kernel โ€” but only if the RPM installed successfully โœ…

uninstall

uninstall [module/module-version] [-k kernel/arch] [--all]
  • uninstalls an installed module/module-version combo from the kernel/arch you passed in the -k option โ€” or the current kernel if you didn't pass -k ๐Ÿ™ˆ
  • use --all to uninstall all instances for every kernel at once. chaos mode but sanctioned
  • after uninstall completes, the driver is left in the built state ๐Ÿ—๏ธ
  • so if you want to completely remove a driver, you need to use the remove action instead. uninstall is not the same as remove, iykyk ๐Ÿ’…

match

match [--templatekernel kernel/arch] [-k kernel/arch]
  • match installs modules onto the specified kernel by peeking at the configuration of the specified templatekernel ๐Ÿ‘€
  • every module that's installed on the templatekernel within dkms gets installed onto that specified kernel too. copy-paste but make it official ๐Ÿฆ‹

mktarball

mktarball [module/module-version] [-k kernel/arch]
          [--archive /path/to/tarball.tar] [--source-only] [--binaries-only]
  • creates a tarball archive for the specified module/version, containing all the files in the DKMS tree for that module/version combination ๐Ÿ“ฆ
  • this includes the source and any built modules for kernels in the tree (as specified) ๐ŸŒˆ
  • otherwise, you can specify a singular kernel to archive, or multiple kernels to archive like -k kernel1/arch1 -k kernel2/arch2 โœจ
  • optionally, use --archive to specify the file you want to save this tarball to ๐ŸŽ€
  • you can also use --binaries-only if you want the resultant tarball to not include the module source ๐Ÿšซ
  • likewise, --source-only means no prebuilt binaries get included in the tarball ๐Ÿ’–
  • in general, mktarball is great for systems management purposes โ€” you can build your driver on just one system, then use ldtarball on all your other systems to get the same built modules loaded without waiting for anything to compile. build once, deploy everywhere, the dream fr fr ๐Ÿ˜ญ๐Ÿ”ฅ

ldtarball

ldtarball [/path/to/tarball.tar] [--force]
  • takes a tarball made from the mktarball command and loads it into your DKMS tree ๐Ÿ“ฅ
  • this leaves any newly added modules in the built state, and then dkms install should be called to install any of them ๐Ÿซถ
  • if files already exist where ldtarball is trying to place them, it will warn and not copy over them โš ๏ธ
  • use --force to override that ๐Ÿ’ฅ

status

status [module/module-version] [-k kernel/arch]
  • returns the current status of modules, versions and kernels within the tree โ€” plus whether they've been added, built, or installed ๐Ÿ”
  • status can be shown for just a certain module, a certain kernel, a module/version combination, or a module/version/kernel combination. so many options, so little time ๐Ÿ’…
  • if the source directory, or the symbolic link source pointing to it, is missing, the status of the module/version combination gets displayed as 'broken' ๐Ÿ’”
  • in that case, dkms will not perform any other action on that particular module/version combination. manual intervention is required, bestie โ€” no autopilot here ๐Ÿšจ
  • if only the symbolic link source is missing, the add action may be used to re-add the module/version combination to dkms ๐Ÿฉน

autoinstall

autoinstall
  • attempts to install the latest revision of all modules that have been installed for other kernel revisions ๐Ÿ”„
  • the DKMS autoinstaller service is a stub that uses this action to perform its work. it's a little helper doing heavy lifting, we love a supportive icon ๐Ÿซถ

generate_mok

generate_mok
  • a command to be issued standalone to generate Secure Boot keys ๐Ÿ”
  • only required if you need to manipulate the keys beforehand โ€” otherwise the keys are automatically generated on the first build attempt of a DKMS module โœจ
  • no additional arguments are parsed. it takes zero notes, zero flags, zero nonsense ๐Ÿ’…

still with me? good, because there's more coming ๐Ÿ‘‘โœจ

โœจ OPTIONS โœจ

Okay bestie, this is the big one โ€” all the little switches and dials you can turn when you run dkms. Every single one is here, no skips, no cap. ๐Ÿ’…

  • -m <module>/<module-version> โ€” The name of the module and the module version you wanna operate on. The -m part of this option is optional and can be omitted in virtually all circumstances. โœจ
  • -v <module-version> โ€” The version of the module to execute the specified action upon. You only have to pass this if you gave a -m option that didn't have its own <module-version> component. ๐ŸŽ€
  • -k <kernel-version>/<arch> โ€” The kernel and arch to perform the action on. You can stack multiple kernel version/arch pairs by repeating -k with a different kernel version and arch. However, not all actions support multiple kernel versions โ€” it will error out in that case. The arch part can be omitted, and DKMS will assume you want the arch of the currently running system. ๐Ÿฆ‹
  • -a, --arch โ€” The system architecture to perform the action upon. It's optional if you pass it as part of the -k option. If you don't specify it, DKMS assumes the arch of the currently running system (uname -m). You can pass multiple arch parameters on the same command line by repeating -a with a different architecture name. When multiple architectures are specified, there must be a 1:1 relationship between -k arguments and -a arguments. DKMS will assume the first -a aligns with the first -k, the second with the second, and so on. For example, if you were to specify:
-k kernel1 -k kernel2 -a i386 -k kernel3 -a i686 -a x86_64

DKMS would process this as: kernel1-i386, kernel2-i686, kernel3-x86_64. ๐Ÿ”ฅ

  • -q, --quiet โ€” Quiet. Shhh. ๐Ÿคซ
  • -V, --version โ€” Prints the currently installed version of dkms and exits. ๐Ÿ‘‘
  • -h, --help โ€” ๐Ÿ†˜ Help flag, bestie.
  • -c <dkms.conf-location> โ€” The location of the dkms.conf file. This is needed for the add action, and if not specified, it is assumed to be located in /usr/src/<module>-<module-version>/. See below for more information on the format of dkms.conf. ๐Ÿ’–
  • --config <kernel-include/config/auto.conf-location> โ€” During a build, this option specifies an alternate location for the kernel include/config/auto.conf configuration file which contains that kernel configuration. Normally, dkms is able to derive the location of the configuration file from the filesystem, but if there's a problem in the detection, you'll need to tell dkms where the necessary include/config/auto.conf file (or the legacy .config file) can be found so your kernel can be properly prepared for the module build. ๐ŸŒธ
  • --archive <tarball-location> โ€” Used during a ldtarball action to specify the location of the tarball you wish to load into your DKMS tree. You only have to specify the --archive part of this option if <tarball-location> does not already exist as a file. ๐ŸŽ€
  • --templatekernel <kernel-version> โ€” Required for the action: match. Match will look at the templatekernel specified and install all of the same module/version combinations on the other kernel. ๐Ÿ’ซ
  • --force โ€” Can be used in conjunction with build, install and ldtarball to force copying over existing files. ๐Ÿ˜ค
  • --force-version-override โ€” Skips the checks whether the version of the module which is going to be installed is newer than the already installed version. โšก
  • --binaries-only โ€” Can be used with mktarball to create a DKMS tarball which does not contain the source for the module within it. This helps reduce the tarball size if you know the system this tarball will be loaded upon already has the source installed. In order to load a tarball made as binaries-only, you must have the module source in that system's DKMS tree. If you don't, DKMS will refuse to load a binaries-only tarball. ๐Ÿšซ
  • --source-only โ€” Can be used with mktarball when you don't want the tarball you create to have any prebuilt modules within it. Passing this option keeps its internal DKMS tarball from containing any prebuilt modules. ๐ŸŒฑ
  • --all โ€” Automatically specifies all relevant kernels/arches for a module/module-version. Can be used for things like remove, unbuild and uninstall. Saves you the trouble of actually specifying -k kernel1 -a arch1 -k kernel2 -a arch2 for every kernel you have built your module for. ๐Ÿซถ
  • --no-depmod โ€” Prevents DKMS from running the depmod command during install and uninstall, which avoids (re)calculating module dependencies and thereby saves time. โฑ๏ธ
  • --modprobe-on-install โ€” Executes modprobe on the modules upon successful installation. ๐Ÿš€
  • --kernelsourcedir <kernel-source-directory-location> โ€” Lets you specify the location of your kernel source directory. Most likely you won't need to set this if your kernel source is accessible via /lib/modules/$kernel_version/build. ๐Ÿ“
  • --directive <"cli-directive=cli-value"> โ€” Lets you specify additional directives from the command line. The --directive option can be used multiple times on the same command line to specify multiple additional command line directives. ๐Ÿ’ฌ
  • --rpm_safe_upgrade โ€” This flag should be used when packaging DKMS enabled modules in RPMs. It should be specified during both the add and remove actions in the RPM spec to ensure that DKMS and RPM behave correctly in all scenarios when upgrading between various versions of a dkms enabled module RPM package. ๐Ÿ“ฆ
  • --dkmstree path/to/place โ€” Provides a destination tree for building and installing modules to. Useful when you don't want to contaminate a system when using it solely for building. ๐ŸŒณ
  • --sourcetree path/to/place โ€” Provides a location to build a DKMS package from. Useful for systems where you may not have root access, but you'd still like to be able to build DKMS packages. ๐Ÿ”จ
  • --installtree path/to/place โ€” Provides a location to place modules when a dkms install command is issued. ๐Ÿ“ฆ
  • -j number โ€” Run no more than number jobs in parallel; see the -j option of make(1). Defaults to the number of CPUs in the system, detected by nproc(1). Specify 0 to impose no limit on the number of parallel jobs. ๐Ÿงต
  • --verbose โ€” Enable verbose output of external commands executed in DKMS. ๐Ÿ—ฃ๏ธ

๐Ÿฆ‹ ORIGINAL MODULES ๐Ÿฆ‹

So, during the first install of a module for a <kernelversion>, dkms will search /lib/modules/<kernelversion> for a pre-existing module of the same name. If one is found, it will automatically be saved as an "original_module" so that if the newer module is later removed, dkms will put the original module back in its place. ๐Ÿซถ

Currently, DKMS searches for these original modules with first preference going to modules located in /lib/modules/<kernelversion>/updates/ followed by $DEST_MODULE_LOCATION (as specified in dkms.conf). If one cannot be found in either location, a find will be used to locate one for that kernel. If none are found, then during a later uninstall, your kernel will not have that module replaced. ๐Ÿ˜ญ

If more than one is found, then the first one located (by preference indicated above) will be considered the "original_module". As well, all copies of the same-named module will be removed from your kernel tree and placed into /var/lib/dkms/<module>/original_module/$kernelver/collisions so that they can be manually accessible later. DKMS will never actually do anything with the modules found underneath the /collisions directory, and they will be stored there until you manually delete them. ๐Ÿ’€


๐ŸŽ€ DKMS.CONF ๐ŸŽ€

When performing an add, a proper dkms.conf file must be found. A properly formatted configuration file is essential for communicating to DKMS how and where the module should be installed. While not all the directives are required, providing as many as possible helps to limit any ambiguity. ๐Ÿ“

Note that dkms.conf is really only a shell-script of variable definitions which are then sourced in by the dkms executable (of the format, DIRECTIVE="directive text goes here"). As well, the directives are case-sensitive and should be given in ALL CAPS. ๐Ÿ” 

It is important to understand that many of the DKMS directives are arrays whose index values are tied together. These array associations can be considered families, and there are currently three such families of directive arrays. MAKE[#] and MAKE_MATCH[#] make up one family. PATCH[#] and PATCH_MATCH[#] make up the second family. The third and largest family consists of BUILT_MODULE_NAME[#], BUILT_MODULE_LOCATION[#], DEST_MODULE_NAME[#], DEST_MODULE_LOCATION[#] and STRIP[#]. When indexing these arrays when creating your dkms.conf, each family should start at index value 0. ๐Ÿงฉ

  • PACKAGE_NAME= โ€” This directive gives the name associated with the entire package of modules. This is the same name that is used with the -m option when building, adding, etc. and may not necessarily be the same as the MODULE_NAME. This directive must be present in every DKMS configuration file. ๐Ÿ‘‘
  • PACKAGE_VERSION= โ€” This directive gives the version associated with the entire package of modules being installed within that dkms package. This directive must be present in every DKMS configuration file. โญ
  • BUILT_MODULE_NAME[#]= โ€” This directive gives the name of the module just after it is built. If your DKMS module package contains more than one module to install, this is a required directive for all of the modules. This directive should explicitly not contain any trailing ".o" or ".ko". Note that for each module within a dkms package, the numeric value of # must be the same for each of BUILT_MODULE_NAME, BUILT_MODULE_LOCATION, DEST_MODULE_NAME and DEST_MODULE_LOCATION, and that the numbering should start at 0 (eg. BUILT_MODULE_NAME[0]="qla2200" BUILT_MODULE_NAME[1]="qla2300"). ๐Ÿ’…

BUILT_MODULE_LOCATION[#]=

Okay so bestie, this one tells DKMS where your built module is actually chillin' after it gets built. ๐Ÿ’…

The pathname here should be given relative to the root directory of your source files โ€” that's the place where your dkms.conf file can be found, iykyk.

If you leave it unset, DKMS expects to find your BUILT_MODULE_NAME[#] in the root directory of your source files. No cap.

โš ๏ธ Real talk: for each module within a dkms package, the numeric value of # must be the same for each of BUILT_MODULE_NAME, BUILT_MODULE_LOCATION, DEST_MODULE_NAME and DEST_MODULE_LOCATION, and the numbering should start at 0.

Like, for example:

BUILT_MODULE_LOCATION[0]="some/dir/"
BUILT_MODULE_LOCATION[1]="other/dir/"

See how the numbers line up? That's the vibe. โœจ


DEST_MODULE_NAME[#]=

This directive lets you specify the name of the module as it should be installed. Basically it'll rename the module from BUILT_MODULE_NAME[#] to DEST_MODULE_NAME[#]. Glow-up for your module fr fr. ๐Ÿ’–

It should explicitly not contain any trailing ".o" or ".ko" โ€” like, do not do that.

If unset, it is assumed to be the same value as BUILT_MODULE_NAME[#].

โš ๏ธ Same rule as before: for each module within a dkms package, the numeric value of # must be the same for each of BUILT_MODULE_NAME, BUILT_MODULE_LOCATION, DEST_MODULE_NAME and DEST_MODULE_LOCATION, and the numbering should start at 0.

Example:

DEST_MODULE_NAME[0]="qla2200_6x"
DEST_MODULE_NAME[1]="qla2300_6x"

DEST_MODULE_LOCATION[#]=

This directive specifies the destination where a module should be installed to, once compiled. It also is used for finding original_modules. ๐Ÿ‘‘

This is a required directive, except as noted below. It must start with the text "/kernel" โ€” which is in reference to /lib/modules/<kernelversion>/kernel.

โš ๏ธ And yes, the same numbering thing AGAIN: for each module within a dkms package, the numeric value of # must be the same for each of BUILT_MODULE_NAME, BUILT_MODULE_LOCATION, DEST_MODULE_NAME and DEST_MODULE_LOCATION, and the numbering should start at 0.

Example:

DEST_MODULE_LOCATION[0]="/kernel/drivers/something/"
DEST_MODULE_LOCATION[1]="/kernel/drivers/other/"

Now the plot twist: DEST_MODULE_LOCATION is ignored on Fedora, Red Hat Enterprise Linux, SuSE Linux Enterprise Server, openSUSE and Ubuntu. Instead, the proper distribution-specific directory is used. So on those distros your cute little path just gets ghosted. ๐Ÿ™ˆ


STRIP[#]=

By default strip is considered to be "yes". If you set it to "no", DKMS will not run strip -g against your built module to remove debug symbols from it. So like, if you're out here debugging and you need those symbols, this is your girl. ๐ŸŽ€

STRIP[0] is used as the default for any unset entries in the STRIP array. Periodt.


MAKE[#]=

The MAKE directive array tells DKMS which make command should be used for building your module. ๐Ÿ› ๏ธ

  • The default make command should be put into MAKE[0].
  • Other entries in the MAKE array will only be used if their corresponding entry in MAKE_MATCH[#] matches, as a regular expression (using grep -E), the kernel that the module is being built for.
  • Heads up: if no value is placed in MAKE_MATCH[#] for any MAKE[#] where # > 0, then that MAKE directive is ignored. ๐Ÿ’€
  • MAKE_MATCH[0] is optional, and if it is populated, it will be used to determine if MAKE[0] should be used to build the module for that kernel.
  • If multiple MAKE_MATCH directives match against the kernel being built for, the last matching MAKE[#] will be used to build your module.
  • If no MAKE directive is specified, or if no MAKE_MATCH matches the kernel being built for, DKMS will attempt to use a generic make command to build your module.

Also, sneaky detail: KERNELRELEASE=$kernelver -j$parallel_jobs will be automatically appended to MAKE[#]. If you want to suppress this behavior, you can quote the make command: 'make'. ๐Ÿซถ


MAKE_MATCH[#]=

See the above entry on MAKE[#] directives, bestie. This array should be populated with regular expressions which, when matched against the kernel being built for, will tell DKMS to use the corresponding make command in the MAKE[#] directive array to build your module. It's giving conditional logic, but make it regex. โœจ


NO_WEAK_MODULES=

The NO_WEAK_MODULES directive, when set to "yes", prevents dkms from creating a symlink into the weak-updates directory. ๐Ÿšซ

The weak modules facility was designed to eliminate the need to rebuild kernel modules when kernel upgrades occur, and it relies on the symbols within the kABI. Valid values are "yes" or "no".

The kABI kernel module interface is currently supported on Red Hat Enterprise Linux (and derivatives), SUSE Linux Enterprise Server and openSUSE Leap; on other distributions this directive is ignored.


OBSOLETE_BY=

โš ๏ธ DEPRECATED ALERT โš ๏ธ This directive is deprecated and will be removed in a future version. Consider using BUILD_EXCLUSIVE_KERNEL_MAX instead of OBSOLETE_BY, as the former is a more general approach to solve the same problem. Like, the upgrade path is right there bestie, take it. ๐Ÿ˜ญ

It allows you to specify a kernel version that obsoletes the necessity for this particular DKMS module. This can be specified as a particular upstream kernel or an ABI bump of a kernel. For example, "2.6.24" would be an upstream kernel and "2.6.24-16" would represent an ABI bump for a kernel. Both are valid in this area. ๐Ÿ‘‘

Its use indicates a lack of proper module versioning using MODULE_VERSION() tags in the module source itself. It is better to fix the MODULE_VERSION() tags than use OBSOLETE_BY. This also introduces an implicit distribution/version dependency on the package, as the value of OBSOLETE_BY is meaningful only in the context of a single distribution/version. So yeah, it's lowkey a red flag in your config. ๐Ÿšฉ


PATCH[#]=

Use the PATCH directive array to specify patches which should be applied to your source before a build occurs. ๐Ÿงต

  • All patches are expected to be in -p1 format and are applied with the patch -p1 command.
  • Each directive should specify the filename of the patch to apply.
  • All patches must be located in the patches subdirectory of your source directory (/usr/src/<module>-<module-version>/patches/) or in /etc/dkms/<module>/patches/ (which takes precedence over the source directory). So like, /etc/dkms is the main character here. ๐Ÿ’…
  • If any patch fails to apply, the build will be halted and the rejections can be inspected in /var/lib/dkms/<module>/<module-version>/build/.
  • If a patch should only be applied conditionally, the PATCH_MATCH[#] array should be used, and a corresponding regular expression should be placed in PATCH_MATCH[#] which will alert dkms to only use that PATCH[#] if the regular expression matches the kernel which the module is currently being built for.

PATCH_MATCH[#]=

See the above description for PATCH[#] directives. If you only want a patch applied in certain scenarios, the PATCH_MATCH array should be utilized by giving a regular expression which matches the kernels you intend the corresponding PATCH[#] to be applied to before building that module. Conditional patching, we love to see it. ๐Ÿฆ‹


AUTOINSTALL=

If this directive is set to "yes" then the DKMS autoinstaller service will automatically try to install this module on any kernel you boot into. See the section on DKMS AUTOINSTALLER for more information. Valid values are "yes" or "no". Set it and forget it, honestly. โœจ


BUILD_DEPENDS[#]=

This optional directive is an array that allows you to specify other modules as dependencies for your module. ๐Ÿซถ

  • Each array element should be the PACKAGE_NAME of another module that is managed by dkms.
  • Do not specify a version or architecture in the dependency.
  • A missing dependency requires the parameter [--force] to still attempt the build of the module.

When invoked through autoinstall, unresolved dependencies are handled differently depending on whether they are known to dkms:

  • A dependency that is itself a dkms-managed module but failed to install (for example because of a circular dependency or a build error) is treated as a hard failure and causes autoinstall to exit non-zero.
  • A dependency that is not registered with dkms at the time autoinstall runs is treated as deferred: a warning is emitted and the dependent module is left in the added state, but autoinstall exits successfully.

This avoids spurious failures during multi-package installs where the dependency's source package has not yet had its postinst run, or where the dependency is supplied by something outside dkms. The dependent module will be picked up by the next autoinstall trigger once the dependency becomes available. Not me being patient and emotionally mature about dependency ordering. ๐Ÿ™ˆ

Example: Ubuntu system with module A and module B depending on A. During an update, both the kernel and module A get updated, so autoinstall runs as a kernel post hook. This means the whole dependency logic fails because module A is not yet installed to satisfy module B.


BUILD_DEPENDS_REBUILD=

If this directive is set to yes then the module which has BUILD_DEPENDS being set will get rebuilt every time a dependency changes version. ๐Ÿ” This is usually provided in a specific /etc/dkms/<module>.conf on a per installation basis.

To keep track of the dependency change, the version of the module that was used at build time is recorded in the file:

/var/lib/dkms/<module>/<kernel_version>-<arch>/.dep_<dependency>

As soon as the module version changes, this is compared and the dependent module is rebuilt. With the parameter --force the dependency is not tracked.


BUILD_EXCLUSIVE_KERNEL=

This optional directive allows you to specify a regular expression which defines the subset of kernels which DKMS is allowed to build your module for. ๐Ÿ‘‘

If the kernel being built for does not match against this regular expression (or does not satisfy the constraints of any other BUILD_EXCLUSIVE_* directive), the build will error out with exit code 77. Note that dkms autoinstall will ignore this type of error condition and simply skip the respective modules. So it's less "screaming" and more "silently walking away". ๐Ÿ’€

For example, if you set it as ="^2.4.*", your module would not be built for 2.6 or later kernels.


okay so bestie, we're still in the dkms.conf zone ๐Ÿ’… and these next bits are all about telling DKMS exactly which kernels and architectures your module is allowed to play with. no cap.

  • BUILD_EXCLUSIVE_KERNEL_MIN= and BUILD_EXCLUSIVE_KERNEL_MAX= โ€” these are optional and they let you set the min and max kernel versions your module supports. if you set one or both, your module won't be built for kernels outside those limits. for example, if you set BUILD_EXCLUSIVE_KERNEL_MIN as "=3.5", your module gets built for "3.5-rc2", "3.6.18" or later, but not for "3.4.999" or earlier. similarly, if you set BUILD_EXCLUSIVE_KERNEL_MAX as ="4.12", your module gets built for "4.11.999", "3.9-rc5" or earlier, but not for "4.12-rc1" or later. periodt.
  • BUILD_EXCLUSIVE_ARCH= โ€” this one is like the kernel one but for architecture. if you set it to ="i.86", your module won't be built for ia32e, x86_64, amd64, s390, etc. it's giving picky but valid. ๐Ÿ’…
  • BUILD_EXCLUSIVE_CONFIG= โ€” this optional directive lets you give a space-separated list of kernel config options ("CONFIG_FOO") that must be enabled in the target kernel's .config file (either compiled in or as a module) or absent (if prefixed with an exclamation mark, e.g. "!CONFIG_BAR") for the module to build. for example, if you set it as ="CONFIG_PCI !CONFIG_PREEMPT_RT", your module only builds for kernels with PCI enabled but the RT patchset disabled. slay. โœจ
  • BUILD_EXCLUSIVE_KERNEL[#]=, BUILD_EXCLUSIVE_KERNEL_MIN[#]=, BUILD_EXCLUSIVE_KERNEL_MAX[#]=, BUILD_EXCLUSIVE_ARCH[#]=, BUILD_EXCLUSIVE_CONFIG[#]= โ€” these are the per-module versions of all the above. they work exactly like the global ones but only apply to the specific module at the given index. so you can have different constraints for each module in a multi-module package. the global BUILD_EXCLUSIVE directives are still checked for backward compatibility, and if any module fails either global or its specific per-module constraints, the build gets excluded. for example, if you have two modules: BUILD_EXCLUSIVE_KERNEL[0]="^5..*" and BUILD_EXCLUSIVE_KERNEL[1]="^6..*" โ€” module 0 only builds for kernel 5.x, module 1 only for 6.x. iconic.
  • POST_ADD= โ€” the name of the script to run after an add is performed. the path should be given relative to the root directory of your source.
  • POST_BUILD= โ€” the name of the script to run after a build is performed. path relative to the root of your source.
  • POST_INSTALL= โ€” the name of the script to run after an install is performed. path relative to the root of your source.
  • POST_REMOVE= โ€” the name of the script to run after a remove is performed. path relative to the root of your source.
  • PRE_BUILD= โ€” the name of the script to run before a build is performed. path relative to the root of your source.
  • PRE_INSTALL= โ€” the name of the script to run before an install is performed. path relative to the root of your source. if the script exits with a non-zero value, the install will be aborted. this is typically used to perform a custom version comparison. so if your script is like โ€œnahโ€, install stops. ๐Ÿ’€

all scripts (POST_ADD, PRE_BUILD, POST_BUILD, PRE_INSTALL, POST_INSTALL, POST_REMOVE) can also be placed in /etc/dkms/<module>/ instead of the module source directory. scripts in /etc/dkms/<module>/ take precedence over scripts in the source directory. so if you want to override, that's where you go. ๐Ÿ’–

โœจ DKMS.CONF VARIABLES โœจ

inside your DKMS config file, you can use certain variables that get replaced at run-time with their values. it's like magic but it's just shell.

  • $kernelver โ€” can be used within a directive definition, and when it's used, the actual kernel version in question gets substituted in its place. this is especially useful in MAKE commands when specifying which INCLUDE statements should be used when compiling your module (e.g. MAKE="make all INCLUDEDIR=/lib/modules/${kernelver}/build/include"). so you don't have to hardcode that path. queen behavior.
  • $kernel_source_dir โ€” holds the value of the location of your kernel source directory. usually, this will be /lib/modules/$kernelver/build, unless otherwise specified with the --kernelsourcedir option. so it's like the home base for your kernel source.

๐ŸŒธ DKMS.CONF OVERRIDES ๐ŸŒธ

you can override directives provided in the module-provided dkms.conf files. every time after a dkms.conf file is read, dkms will look for and read the following files in order:

  • /etc/dkms/<module>.conf
  • /etc/dkms/<module>-<module-version>.conf
  • /etc/dkms/<module>-<module-version>-<kernel>.conf
  • /etc/dkms/<module>-<module-version>-<kernel>-<arch>.conf

you can use these files to override settings in the module-provided dkms.conf file. so if you need to tweak something without touching the source, this is the move. ๐Ÿ’…

additionally, patches and scripts can be placed in /etc/dkms/<module>/ to override those provided by the module source tree:

  • /etc/dkms/<module>/patches/ โ€” patch files (override same-named patches from the source directory; the directory structure is preserved, so patches in subdirectories such as /etc/dkms/<module>/patches/subdir/patch.patch will override the corresponding subdir/patch.patch from the source tree)
  • /etc/dkms/<module>/ โ€” scripts referenced by PRE_BUILD, POST_BUILD, etc. (override same-named scripts from the source directory)

so if you want to be extra and customize everything, you can. no judgement. ๐Ÿซถ

๐Ÿ‘‘ FRAMEWORK.CONF MAIN CONFIGURATION ๐Ÿ‘‘

the /etc/dkms/framework.conf configuration file controls how the overall DKMS framework handles. it is sourced in every time the dkms command is run. mainly it can currently be used to set different default values for the variables. the file contains descriptions for each directive it supports. additionally to /etc/dkms/framework.conf, any file matching the glob /etc/dkms/framework.conf.d/*.conf will be loaded as well. so you can split your config if you want. very modular, very chic. โœจ

  • dkms_tree, source_tree, install_tree, tmp_location โ€” control which folders DKMS uses for components and artifacts. like where it puts its stuff.
  • verbose โ€” can be set to anything but a null value to enable verbose output of external commands executed in DKMS. so if you want the tea, set it. โ˜•
  • symlink_modules โ€” controls whether binary modules are copied to /lib/modules or if only symlinks are created there. note that these variables can also be manipulated on the command line with --dkmstree, --sourcetree, --installtree and --symlink-modules options. so you have options, bestie.
  • autoinstall_all_kernels โ€” used by the common postinst for DKMS modules. it controls if the build should be done for all installed kernels or only for the current and latest installed kernel. it has no command line equivalent. so it's a config-only vibe.
  • sign_file โ€” this is the path of the sign-file kernel binary that is used to sign the kernel modules. the variable $kernelver can be used in path to represent the target kernel version. the path for the binary depends on the distribution. so you might need to look it up for your distro.
  • mok_signing_key, mok_certificate โ€” location of the key and certificate files used for Secure boot. the variable $kernelver can be used in path to represent the target kernel version. NOTE: if any of the files specified by mok_signing_key and mok_certificate are non-existent, dkms will re-create both files. mok_signing_key can also be a "pkcs11:..." string for PKCS#11 engine, as long as the sign-file program supports it. so secure boot is handled, but watch out for it recreating files. ๐Ÿ˜ญ
  • modprobe_on_install โ€” automatically load the built modules upon successful installation. so you don't have to modprobe manually. convenient. ๐Ÿ’…
  • parallel_jobs โ€” run no more than this number of jobs in parallel. so if you have a beefy machine, you can crank it up. but don't go overboard.
  • compress_gzip_opts, compress_xz_opts, compress_zstd_opts โ€” control how modules are compressed. by default, the highest available level of compression is used. so it's already trying its best. ๐Ÿ’–
  • build_environment โ€” if the directive is set to any non null-value, when building modules, the exported variables that are in the file will be imported into the DKMS shell with the source command. can be used to specify a custom gcc installed in a custom path; and the variable $kernelver can be used inside the environment file to represent the target kernel version. some examples: define a custom script to point to a specific GCC (export CC=/opt/gcc12/bin/gcc): build_environment="/opt/gcc12/env"; enable the software collection gcc-toolset-11 and use it for building an UEK kernel on Oracle Linux: build_environment="/opt/rh/gcc-toolset-11/enable". so you can have different toolchains per build. very flexible. ๐Ÿ”ฅ
  • post_transaction โ€” if the directive is set to any non null-value, the content of the directive will be executed with any command that change the content of the kernel modules folder, that is dkms autoinstall, dkms install and dkms remove/unbuild/uninstall. can be used to trigger a global initrd rebuild or to call a script that performs some other tasks (calling kexec, triggering the restart of services not contained in a DKMS package, etc.). the command is constructed with the shell built-in eval and the variable $kernelver can be used to represent the target kernel version. some examples: regenerate the ram disk for the target kernel: post_transaction="dracut --force --kver $kernelver" (Red Hat style) or post_transaction="update-initramfs -k $kernelver" (Debian style); launch an arbitrary script: post_transaction="/path/to/script.sh"; restart a service: post_transaction="systemctl restart something.service"; regenerate the ram disk for all installed kernels, ignoring the kernel version passed as the parameter: post_transaction="dracut --force --regenerate-all" (Red Hat style) or post_transaction="update-initramfs -k all" (Debian style). so it's like a hook after any kernel module folder change. powerful stuff. ๐Ÿ‘‘

๐Ÿฆ‹ DKMS AUTOINSTALLER ๐Ÿฆ‹

the DKMS autoinstaller service (which can be dkms_autoinstaller or dkms.service depending on your distribution) is a boot-time service that automatically installs any module which has AUTOINSTALL="yes" set in its dkms.conf file. the service works quite simply and if multiple versions of a module are in your system's DKMS tree, it will not do anything and instead explain that manual intervention is required. so it's like โ€œi got you, but if it's complicated, you're on your ownโ€. fair. ๐Ÿ™ˆ

๐ŸŒˆ AUTHOR ๐ŸŒˆ

Gary Lerhaupt, Emil Velikov, Simone Caronni, Xu Zhen

๐ŸŒ WEBPAGE ๐ŸŒ

okay bestie so if you wanna go stare at the source of truth with your own two eyeballs, the official webpage is:

https://github.com/dkms-project/dkms

like. that's the whole section. short and sweet, we love a low-effort queen ๐Ÿ’…โœจ


aaaand that's a wrap on the whole DKMS(8) page, bestie!! ๐ŸŽ€ you just read all of it, every flag, every variable, every config file, every warning, no skips, no cap. that's genuinely iconic of you ๐Ÿซถ

this version was dkms-3.4.4, and it's dated 05 Oct 2026 โ€” so if you're reading this and the calendar says otherwise, maybe go peek at the repo above for something fresher ๐Ÿ‘‘๐ŸŒธ

go build something, go load a module, go be the main character of your own kernel ๐Ÿ’– byeee!! ๐Ÿฆ‹โœจ

๐Ÿ“ฆ where this page comes from