Using modules in Fedora

Modules are special package groups usually representing an application, a language runtime, or a set of tools. They are available in one or multiple streams which usually represent a major version of a piece of software, giving you an option to choose what versions of packages you want to consume.

To simplify installation, modules usually define one or more installation profiles that represent a specific use case. For example a server or a client profile in a database module.

This is a quick overview how to use modules and module streams with the package manager DNF.

Module stream installation and discovery

Listing packages

Packages available to the system can be discovered by the usual commands such as dnf search NAME, dnf list NAME, or by using the dnf repoquery QUERY command for more complex queries. However, it is important to note that those commands will, apart from traditional packages, only list modular packages coming from already enabled module stream.

Listing modules

To list modules available to your system, and to see what streams are default or have been enabled, use the following command:

    $ dnf module list

Installing packages

Packages can be installed the usual way by running the dnf install NAME command. Any traditional package, or a modular package coming from an enabled module can be installed this way.

Packages from other module streams can be consumed by either enabling a module stream and then installing individual packages, or by installing a module directly.

Enabling modules

To enable a module stream and make its packages available for installation, run the following command:

    $ dnf module enable NAME:STREAM

For example, to make Node.js 8 packages available for installation, run:

    $ dnf module enable nodejs:8

Packages from enabled module streams can be then installed by the dnf install NAME command.

Installing modules

To install a module, use one of the following commands. Not specifying a stream or a profile causes DNF to choose the default. However, not every module has a default stream or a default profile. In that case you need to specify the stream or the profile explicitly.

    $ dnf module install NAME
    $ dnf module install NAME:STREAM
    $ dnf module install NAME/PROFILE
    $ dnf module install NAME:STREAM/PROFILE

For example, to install the Node.js 8 runtime and the client tooling of the default stream of MongoDB, run:

    $ dnf module install nodejs:8
    $ dnf module install mongodb/client

Switching module streams

Switching streams is a risky operation that might not be always supported in packages, especially downgrades.

Switching to a different stream than the one that is installed on a system done with the switch-to argument.

    $ dnf module switch-to NAME:STREAM

An example, to switch from Node.js 8 to Node.js 10, run:

    $ dnf module switch-to nodejs:10

An example, to switch from Node.js 10 to Node.js 8, run:

    $ dnf module switch-to nodejs:8
The switch-to argument is the recommended and prefered way to switch streams.

The switch-to argument includes multiple actions which need to be executed to safetly switch to another module stream.

In this example we show a manual switch from Node.js 8 to Node.js 10 without the switch-to argument run:

    $ dnf remove nodejs
    $ dnf module reset nodejs:8
    $ dnf module enable nodejs:10
    $ dnf install nodejs
The dnf module info NAME:STREAM command is helpful to check RPMs in a module stream.

Updating the system

Updating a system by running the dnf update command causes all packages to be upgraded to their latest version provided by their module stream.

Removing modules

In general, to remove a module installed on your system, use the following command:

    $ dnf module remove MODULE:STREAM/PROFILE

Advanced

There is a situation when a specific package has been installed first, and then a module has been installed after that. Example:

    $ dnf install ruby
    $ dnf module install ruby:2.6/default

In this case, running the dnf module remove command would not remove the ruby package, as DNF remembers that package has been explicitly installed.

To make the ruby package uninstalled with the dnf module remove command, run the following:

    $ dnf mark group ruby
    $ dnf module remove ruby:2.6/default

That is because DNF remembers a reason why a package has been installed. There are three, sorted from the strongest:

  • user

  • group

  • dependency

Because modules use the group reason, which is weaker than user used by the dnf install command, the package stays on the system after running the dnf module remove command. "Downgrading" it to group, however, makes the dnf module remove remove it as well.

Modular filtering and conflicts

When consuming module streams a lot of operations are being executed. A module stream contains alternative modular RPM packages which can have the same name as already existing non-modular RPM packages, a lot of conflicts can arise. In the next few examples we will show you some of the conflicts.

Switching a module stream without removing the RPM packages from the old module stream

Example 1. broken dependencies when switching module streams without removing the installed content
[root@5e7d134a8883 /]# dnf module install nodejs:14/common
Last metadata expiration check: 0:02:38 ago on Thu Mar  3 08:57:00 2022.
Dependencies resolved.

 Problem 1: cannot install the best candidate for the job
  - nothing provides /usr/bin/pwsh needed by nodejs-1:14.19.0-2.module_f35+13766+ad18d3e5.x86_64
 Problem 2: package npm-1:6.14.16-1.14.19.0.2.module_f35+13766+ad18d3e5.x86_64 requires nodejs = 1:14.19.0-2.module_f35+13766+ad18d3e5, but none of the providers can be installed
  - cannot install the best candidate for the job
  - nothing provides /usr/bin/pwsh needed by nodejs-1:14.19.0-2.module_f35+13766+ad18d3e5.x86_64
===========================================================================================================================================================================
 Package                             Architecture              Version                                                            Repository                          Size
===========================================================================================================================================================================
Upgrading:
 nodejs                              x86_64                    1:14.17.2-2.module_f35+12348+fe4be0bd                              fedora-modular                      93 k
 nodejs-docs                         noarch                    1:14.17.2-2.module_f35+12348+fe4be0bd                              fedora-modular                     6.0 M
 nodejs-full-i18n                    x86_64                    1:14.17.2-2.module_f35+12348+fe4be0bd                              fedora-modular                     7.8 M
 nodejs-libs                         x86_64                    1:14.17.2-2.module_f35+12348+fe4be0bd                              fedora-modular                      13 M
Downgrading:
 npm                                 x86_64                    1:6.14.13-1.14.17.2.2.module_f35+12348+fe4be0bd                    fedora-modular                     3.3 M
Installing module profiles:
 nodejs/common
Skipping packages with broken dependencies:
 nodejs                              x86_64                    1:14.19.0-2.module_f35+13766+ad18d3e5                              updates-modular                    199 k
 npm                                 x86_64                    1:6.14.16-1.14.19.0.2.module_f35+13766+ad18d3e5                    updates-modular                    3.3 M

Transaction Summary
===========================================================================================================================================================================
Upgrade    4 Packages
Downgrade  1 Package
Skip       2 Packages

Total download size: 30 M
Is this ok [y/N]:

In this situation we enabled and installed the nodejs:12 module stream on Fedora 35. Then we reset the 12 stream and enabled the 14 stream. After that we wanted to install the nodejs:14 module stream.

First DNF is trying to upgrade or downgrade the existing installed software. It will not remove the existing software during the execution of the reset argument. The reset only disables the enabled stream of a module. The NEVRAs of the RPM files in the module stream can have different versions from the installed software (newer or older) and also from other streams from the same module. The runtime dependencies can be different between RPM packages from different module streams.

This conflict is correct and is not a bug. As you are trying to update installed RPM packages from the 12 stream with RPM packages from the 14 stream. Module streams from the same module are mutually exclusive and only one stream at a time should be enabled and installed.

If you are switching streams and not sure about the manual process, please use the switch-to argument as this is the recommended way.

Installing a RPM package from a wrong module stream.

Example 2. of a RPM package requested to be installed from the wrong module stream
[root@bdaeaab947e6 /]# dnf module enable perl:5.30
Fedora 35 - x86_64                                                                                                                         6.8 MB/s |  79 MB     00:11
Fedora 35 openh264 (From Cisco) - x86_64                                                                                                   3.1 kB/s | 2.5 kB     00:00
Fedora Modular 35 - x86_64                                                                                                                 2.8 MB/s | 3.3 MB     00:01
Fedora 35 - x86_64 - Updates                                                                                                               7.3 MB/s |  27 MB     00:03
Fedora Modular 35 - x86_64 - Updates                                                                                                       2.3 MB/s | 2.8 MB     00:01
Dependencies resolved.
===========================================================================================================================================================================
 Package                                  Architecture                            Version                                   Repository                                Size
===========================================================================================================================================================================
Enabling module streams:
 perl                                                                             5.30

Transaction Summary
===========================================================================================================================================================================

Is this ok [y/N]: y
Complete!
[root@bdaeaab947e6 /]# dnf install perl-Tie-RefHash
Last metadata expiration check: 0:00:22 ago on Thu Mar  3 09:41:23 2022.
Error:
 Problem: package perl-Tie-RefHash-1.40-478.fc35.noarch requires perl(:MODULE_COMPAT_5.34.0), but none of the providers can be installed
  - conflicting requests
  - package perl-libs-4:5.34.0-481.fc35.i686 is filtered out by modular filtering
  - package perl-libs-4:5.34.0-481.fc35.x86_64 is filtered out by modular filtering
  - package perl-libs-4:5.34.0-482.fc35.i686 is filtered out by modular filtering
  - package perl-libs-4:5.34.0-482.fc35.x86_64 is filtered out by modular filtering
(try to add '--skip-broken' to skip uninstallable packages)
[root@bdaeaab947e6 /]#

The example describes a situation when you try to install a RPM package which is not provided from the enabled perl:5.30 module stream. We first enable the perl:5.30 module stream. After that we are trying to install the package perl-Tie-RefHash. The DNF package manager is trying to tell you that the perl-Tie-RefHash cannot be installed because it is not provided by any of the enabled module streams. Modular filtering will automatically filter out all the RPM packages which are not provided by the actual enabled module streams.

To fix this conflict you have to enable the correct module stream. In our case it is the perl:5.32 module stream.

Installing a RPM package without enabling the module stream which provides it.

Example 3. of a installation conflict when installing a package without enabling the correct module stream
[root@bdaeaab947e6 /]# dnf install perl-DBI
Last metadata expiration check: 3:13:30 ago on Thu Mar  3 09:41:23 2022.
Error:
 Problem: package perl-DBI-1.643-10.fc35.x86_64 requires libperl.so.5.34()(64bit), but none of the providers can be installed
  - conflicting requests
  - package perl-libs-4:5.34.0-481.fc35.x86_64 is filtered out by modular filtering
  - package perl-libs-4:5.34.0-482.fc35.x86_64 is filtered out by modular filtering
(try to add '--skip-broken' to skip uninstallable packages)
[root@bdaeaab947e6 /]# dnf module enable perl-DBI
Last metadata expiration check: 3:14:38 ago on Thu Mar  3 09:41:23 2022.
Dependencies resolved.
===========================================================================================================================================================================
 Package                                  Architecture                            Version                                   Repository                                Size
===========================================================================================================================================================================
Enabling module streams:
 perl-DBI                                                                         1.643

Transaction Summary
===========================================================================================================================================================================

Is this ok [y/N]: y
Complete!
[root@bdaeaab947e6 /]# dnf install perl-DBI
Last metadata expiration check: 3:14:46 ago on Thu Mar  3 09:41:23 2022.
Dependencies resolved.
===========================================================================================================================================================================
 Package                          Architecture                   Version                                                      Repository                              Size
===========================================================================================================================================================================
Installing:
 perl-DBI                         x86_64                         1.643-7.module_f35+12493+425c54a8                            fedora-modular                         700 k

Transaction Summary
===========================================================================================================================================================================
Install  1 Package

Total download size: 700 k
Installed size: 1.9 M
Is this ok [y/N]:

In this example we are trying to install the perl-DBI package. On our system we have previously enabled and installed the perl:5.32 module stream. The conflict tells us that we are trying to install non-modular perl-DBI which depends on the non-modular perl but the non-modular perl package is not available due to modular filtering. The only RPM packages which are available for dependency resolution are the RPM packages from the 5.32 stream.

Non-modular RPM packages can not depend on modular content. If your non-modular package needs a modular dependency please modularize your content.

To fix this we need to enable the perl-DBI:1.643 module stream. When enabling the perl-DBI:1.643 we are satisfying the modular dependency for the perl module. The non-modular perl-DBI RPM package is now filtered by modular filtering and it is not considered in dependency resolution and content set creation.