Modular DNF Behavior

This page has been archived. It contains information that is either no longer true, relevant, or it should not be part of this documentation. It has been kept for historical reasons and can be removed at any time.

This page captures the key behaviors of modular DNF.


  • Ursine ("bare") packages are those that are not part of any module.

  • A module’s "context" is a unique hash value generated by the build system to distinguish binaries built for different Fedora releases as a result of stream expansion. See [module-stream-expansion].


  • Existing use of RPM-based operations must not change and must continue to work just as they always have.

  • DNF install/update commands can be invoked by using syntax of either dnf module <command> $modspec …​ or dnf <command> @$modspec …​.

  • The "platform" pseudo-module cannot be explicitly enabled, installed, deleted, or have its stream changed.

  • A module is specified by its name, stream, version, context, and architecture (e.g., "module:stream:version:context:arch").

    • If a module has a default stream defined on a system, "stream" may be omitted. Otherwise, "stream" must be explicitly provided.

    • For a given "module:stream", "version" can always be omitted. If "version" is not explicitly provided, the latest "version" for the given "module:stream" will be chosen.

    • If the module "context" is not specified, DNF will use heuristics to determine the appropriate "context". See [module-stream-expansion].

    • If the module "arch" is not specified, the system’s base architecture will be used.

    • Specifying a non-existent "module" name should fail.

    • Specifying a non-existent "stream" (for a valid "module") should fail.

    • Specifying specifying a non-existent "version" (for a valid "module:stream") should fail.

    • Specifying specifying a non-existent "context" (for a valid "module:stream:version") should fail.

    • Specifying a non-existent "arch" (for a valid "module:stream:version:context") should fail.

System modular defaults

  • DNF must look for modular default stream and installation profile data in the repodata of the package installation repos—​which is sourced from [fedora-module-defaults-repo] during the Fedora build and release process.

  • DNF must look for override data for modular default stream and installation profile on the local system in /etc/dnf/modules.defaults.d/.

Module listing

  • DNF must be able to list all modular content (modules, streams, enabled streams, default streams, profiles, module packages, profile packages).

Module enablement

  • Enabling a module stream makes all of its packages available on the system, but does not install them.

  • At most one stream of a module may be enabled at a time on a system.

Module Auto-enablement

  • If an uninstalled/unenabled module has a valid default stream configured, DNF will consider the default stream of the module and all of its packages available for resolving dependencies—​and will automatically enable the default stream of that module if any packages from it are installed directly or indirectly (to resolve dependencies).

  • If an uninstalled/unenabled module:stream is listed as a runtime dependency of another module being installed or enabled, DNF will automatically enable that dependency.

  • Once a particular stream of a module has been enabled, DNF may not automatically enable a different stream.

Module/package installation

  • Installing a module enables the specified stream (or default stream, if not specified) and installs all of the packages associated with the specified profile (or "default" profile, if not specified).

  • If a module does not explicitly have a "default" profile specified it its modulemd, DNF must pretend that it exists and is empty. See [mmd-spec-v2].

  • Each profile of a module stream must be able to be installed. However, a module’s profiles may conflict amongst themselves such that they cannot all be installed at the same time. (A hypothetical example would be a module that provides something analogous to the coreutils and coreutils-single packages in different profiles. The coreutils packages provide the same functionality, but conflict.)

Switching module streams

  • This operation is not currently allowed. The currently enabled stream needs to be either reset or disabled before a different stream will be available for enablement or installation.

Module update

  • Updating a module will update all installed packages that belong to the enabled module stream—​regardless if the packages were installed by an install profile or ad hoc.

Module disablement

  • Disabling a module does not remove any packages that belong to the module.

  • Disabling a module disables modules that depend on it—​unless they still have packages installed.

Module removal

  • Uninstalling a module removes all the packages that belong to the module and disables it.

  • Ad hoc removal of all packages from an installed module does not disable the module.

Module locking

  • A locked module cannot have a different stream enabled or be disabled—​without first unlocking it.

Stream expansion and contexts


  • Any package in an enabled module takes priority over any ursine RPM with the same package name, regardless of which repositories those modules and packages may be in.

  • If there’s an ursine or modular RPM with a higher NVR than the hotfix one, the ursine or modular one wins. This is to ensure new proper updates override the temporary hotfix RPMs.