Chapter 23. Software management


The following chapter contains the most notable changes to software management between RHEL 8 and RHEL 9.

In Red Hat Enterprise Linux 9, software installation is ensured by DNF. Red Hat continues to support the usage of the yum term for consistency with previous major versions of RHEL. If you type dnf instead of yum, the command works as expected because both are aliases for compatibility.

Although RHEL 8 and RHEL 9 are based on DNF, they are compatible with YUM used in RHEL 7.

For more information, see Managing software with the DNF tool.

23.2. Notable changes to Image mode for RHEL

Image mode for RHEL users can now use dnf --transient to perform package transactions that reset on reboot

Previously, Image mode for RHEL users could transiently install, remove, and upgrade packages by running the bootc usr-overlay command to unlock the system and then make changes by running DNF commands. If you use bootc usr-overlay, when the system reboots, the /usr directory overlay disappears and all changes made to it will reset. Changes to other directories, including configuration in /etc and program state in /var, persist across reboots.

With RHEL 9.6, a new --transient flag and a new persistence configuration option have been added to DNF to improve the user experience on bootc systems. You can now skip the bootc usr-overlay step by using either of the following options:

  • Use the dnf --transient command.
  • Set the persistence option to transient in the dnf.conf file.
Note

Unlike when using bootc usr-overlay, --transient and persistence=transient ensure that the /usr directory remains read-only to other processes before, during, and after the transaction.

For example, to transiently install the make package, enter:

# dnf install --transient make
Copy to Clipboard Toggle word wrap

23.3. Notable RPM features and changes

Red Hat Enterprise Linux 9 is distributed with RPM version 4.16. This version introduces many enhancements over its previous versions.

Notable features include:

  • New SPEC features, most notably:

    • Fast macro-based dependency generators

      It is now possible to define dependency generators as regular RPM macros. This is especially useful in combination with the embedded Lua interpreter (%{lua:…​}) because it enables writing sophisticated yet fast generators and avoiding redundant forking and executing a shell script.

      Example:

      %__foo_provides()    %{basename:%{1}}
      Copy to Clipboard Toggle word wrap
    • The %generate_buildrequires section that enables generating dynamic build dependencies

      Additional build dependencies can now be generated programmatically at RPM build time, using the newly available %generate_buildrequires section. This is useful when packaging software written in a language in which a specialized utility is commonly used to determine run-time or build-time dependencies, such as Rust, Golang, Node.js, Ruby, Python or Haskell.

    • Meta (unordered) dependencies

      A new dependency qualifier called meta enables expressing dependencies that are not specifically install-time or run-time dependencies. This is useful for avoiding unnecessary dependency loops that could otherwise arise from the normal dependency ordering, such as when specifying the dependencies of a meta package.

      Example:

      Requires(meta): <pkgname>
      Copy to Clipboard Toggle word wrap
    • Native version comparison in expressions

      It is now possible to compare arbitrary version strings in expressions by using the newly supported v"…​" format.

      Example:

      %if v"%{python_version}" < v"3.9"
      Copy to Clipboard Toggle word wrap
    • Caret version operator, opposite of tilde

      The new caret (^) operator can be used to express a version that is higher than the base version. It is a complement to the existing tilde (~) operator which has the opposite semantics.

    • %elif, %elifos and %elifarch statements
    • Optional automatic patch and source numbering

      Patch: and Source: tags without a number are now automatically numbered based on the order in which they are listed.

    • %autopatch now accepts patch ranges

      The %autopatch macro now accepts the -m and -M parameters to limit the minimum and maximum patch number to apply, respectively.

    • %patchlist and %sourcelist sections

      It is now possible to list patch and source files without preceding each item with the respective Patch: and Source: tags by using the newly added %patchlist and %sourcelist sections.

    • A more intuitive way to declare build conditionals

      Starting from RHEL 9.2, you can use the new %bcond macro to build conditionals. The %bcond macro takes a build conditional name and the default value as arguments. Compared to the old %bcond_with and %bcond_without macros, %bcond is easier to understand and allows you to calculate the default value at build time. The default value can be any numeric expression.

      Example:

      • To create a gnutls build conditional, enabled by default:

        %bcond gnutls 1
        Copy to Clipboard Toggle word wrap
      • To create a bootstrap build conditional, disabled by default:

        %bcond bootstrap 0
        Copy to Clipboard Toggle word wrap
      • To create an openssl build conditional, defaulting to opposite of gnutls:

        %bcond openssl %{without gnutls}
        Copy to Clipboard Toggle word wrap
    • %patch N no longer applies a patch number 0

      Previously, when you used the %patch N syntax, where N is the number of a patch, the syntax also applied the patch number 0 (Patch0) in addition to the patch specified by N.

      In RHEL 9.6, the %patch N syntax has been fixed to only apply the patch number N.

      Important

      If you use the %patch directive without a patch number specified, as a shorthand for %patch 0, Patch0 is applied. However, a warning is printed that suggests you use the explicit syntax, for example, %patch 0 or %patch -P 0 instead of %patch to apply the zero-th patch.

  • The RPM database is now based on the sqlite library. Read-only support for BerkeleyDB databases has been retained for migration and query purposes.
  • A new rpm-plugin-audit plug-in for issuing audit log events on transactions, previously built into RPM itself
  • Increased parallelism in package builds

    There have been numerous improvements to the way the package build process is parallelized. These improvements involve various buildroot policy scripts and sanity checks, file classification, and subpackage creation and ordering. As a result, package builds on multiprocessor systems, particularly for large packages, should now be faster and more efficient.

  • Enforced UTF-8 validation of header data at build-time
  • RPM now supports the Zstandard (zstd) compression algorithm

    In RHEL 9, the default RPM compression algorithm has switched to Zstandard (zstd). As a result, packages now install faster, which can be especially noticeable during large transactions.

Back to top
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust. Explore our recent updates.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Theme

© 2025 Red Hat