Red Hat Certified System Administrator (RHCSA) #8 Packages and repositories: dnf, modules, AppStream

9 min read

Through #7 File systems we wrapped up storage and mounting. To run a system, you have to put software on top of it, and the standard tool for handling software on RHEL is dnf. In this post we cover the fundamentals of installing, removing, and searching packages with dnf, how to add a repository, the AppStream module streams and profiles that arrived with RHEL 8, and working directly with rpm underneath dnf.

In RHCSA, the package area doesn’t have many tasks, but it’s an area where you can lock in points reliably. Questions like “add a specific repository and install a package from it” or “enable a specific module stream and install” come up as staples, so drilling the commands secures points in a short time.

The relationship between dnf and rpm #

RHEL packages are in rpm format, and the low-level tool for installing an individual rpm file is the rpm command. But rpm doesn’t resolve dependencies automatically. If you want to install a package and it needs another package, you have to find that dependency yourself and install it alongside.

The higher-level tool that solves that inconvenience is dnf. dnf pulls metadata from a repository, resolves dependencies automatically, and downloads and installs the required packages together. It’s the successor to the yum used through RHEL 7, and from RHEL 8 on, yum is just an alias for dnf. So on the exam, use dnf — but the yum you’re used to gives the same result.

ToolRole
rpmInstall, query, verify individual rpm files. No automatic dependency resolution
dnfRepository-based. Automatic dependency resolution, search, groups, module management

In short, the practice is to do everyday installs with dnf and reach for rpm when you need to query or verify an installed package.

dnf basic commands #

Install, remove, update #

These three are the foundation.

dnf install httpd            # install a package
dnf install httpd mod_ssl    # several packages at once
dnf install -y httpd         # auto-approve the confirmation prompt
dnf remove httpd             # remove
dnf update                   # update the whole system
dnf update httpd             # update just a specific package

On the exam, auto-approving with -y is faster than confirming each prompt individually.

Search and information lookup #

Search when you don’t know the exact package name.

dnf search web server    # search packages by keyword
dnf info httpd           # version, summary, license, and other details
dnf list available       # list of installable packages
dnf list installed       # list of installed packages

Finding the source package of a file with provides #

This is an especially useful command in RHCSA. When you don’t know “which package a given command or file lives in,” trace it back with provides.

# find the package that provides a specific command
dnf provides /usr/sbin/semanage

# wildcards in the path work too
dnf provides */htpasswd

For example, if you need semanage but the command isn’t there, the command above lets you find that the policycoreutils-python-utils package provides it, and then install it.

Package groups #

A unit that bundles several packages together is a group. Collections of packages you’d install all at once, like development tools or a server environment, are handled as groups.

dnf group list                          # list of groups
dnf group list hidden                    # including hidden groups
dnf group info "Development Tools"        # check the packages it includes
dnf group install "Development Tools"     # install a group
dnf group remove "Development Tools"      # remove a group

Group names contain spaces, so wrap them in quotes. The old joined-up spelling like dnf groupinstall still works, but on RHEL 9 dnf group install is recommended.

dnf history #

dnf records every transaction. With this record you can check past work and roll back a botched install in one go.

dnf history             # transaction history
dnf history info 5      # details of a specific transaction
dnf history undo 5      # roll back that transaction
dnf history undo last   # roll back the last action

When you do an install wrong, undo conveniently cleans up in one shot the packages that transaction touched.

Working with repositories #

The place where dnf finds packages is a repository. The configuration lives in .repo files under /etc/yum.repos.d/.

Checking the current repositories #

dnf repolist        # list of enabled repositories
dnf repolist all    # full list including disabled ones

Adding a repository with config-manager #

The simplest way to add a URL-form repository is dnf config-manager.

dnf config-manager --add-repo https://example.com/repo/myrepo.repo   # add by URL
dnf config-manager --set-enabled myrepo                              # enable
dnf config-manager --set-disabled myrepo                             # disable

If config-manager isn’t there, you can install it with dnf install -y dnf-plugins-core.

Writing a .repo file by hand #

Questions that have you specify baseurl and gpgcheck directly come up often on the exam. Create a .repo file under /etc/yum.repos.d/ and write it like this.

[myrepo]
name=My Custom Repository
baseurl=http://content.example.com/rhel9/BaseOS
enabled=1
gpgcheck=0

Each item means the following.

KeyMeaning
[myrepo]The repository identifier (ID). The short name in brackets
nameA human-readable description
baseurlWhere the packages are. http://, https://, file:// are all possible
enabledWhether it’s enabled. 1 means in use
gpgcheckWhether to verify the package signature. 1 verifies, 0 skips

If you set gpgcheck to 1, you also have to specify the key location in gpgkey=. If no key information is given on the exam, leaving it at gpgcheck=0 is the safe choice.

# after creating the .repo file, confirm it's recognized
dnf repolist
dnf install -y mypackage

Local repository #

When using a mounted ISO or a local directory as a repository, use file:// in baseurl.

[localmedia]
name=Local Media
baseurl=file:///mnt/repo/BaseOS
enabled=1
gpgcheck=0

This lets you install packages from a local path without internet access. It fits the exam environment well, since the internet is typically blocked, so it’s worth getting familiar with.

AppStream and modules #

From RHEL 8, the default repository splits in two.

RepositoryContents
BaseOSThe core components of the OS. Kernel, basic tools, and so on
AppStreamApplications and runtimes. Databases, languages, web servers, and so on

The heart of AppStream is the module. It’s a structure for providing a single piece of software in multiple versions, and the following two concepts matter.

  • stream: A version branch of the same software. For example, the 18 stream and the 20 stream of nodejs
  • profile: What configuration to install that stream with. For example, common, minimal, development

Module list and info #

dnf module list          # list all modules
dnf module list nodejs   # the streams and profiles of a specific module
dnf module info nodejs   # module details

In the output of dnf module list nodejs, the [d] next to a stream means the default stream, [e] means the enabled stream, and [i] marks installed.

Enabling and installing a stream #

To use a specific version, enable that stream and then install.

dnf module enable nodejs:18          # enable a specific stream
dnf module install nodejs:18         # install with the stream specified (enable+install)
dnf module install nodejs:18/minimal # specify the profile too

When you specify a stream like dnf module install nodejs:18, enable and install are handled together, so finishing with this single line is faster on the exam.

Switching streams #

To switch versions when another stream is already installed, reset with reset and then install the stream you want.

dnf module reset nodejs        # reset the currently enabled/installed module
dnf module install nodejs:20   # install the stream you want
dnf module list nodejs         # confirm the switch

You can’t enable two streams of the same module at once. That’s why a version switch always follows the pattern of reset then reinstall. If an exam question asks you to remove the existing version and switch to a different stream, just remember this order.

Working with rpm directly #

Use the rpm command to check state after installing with dnf, or to handle an individual rpm file. It’s good to memorize the query options as a set.

rpm -qa                              # list all installed packages
rpm -q httpd                         # whether a specific package is installed
rpm -qf /etc/httpd/conf/httpd.conf   # file -> owning package
rpm -ql httpd                        # package -> list of installed files
rpm -qi httpd                        # package description info
rpm -qc httpd                        # narrow down to config files only
rpm -qd httpd                        # view documentation files

-qf and -ql point in opposite directions: -qf finds the owning package from a file path, and -ql lists all files belonging to a package. They’re easy to mix up, so remember “f is for finding the package, l is for listing files.”

Verifying changes with rpm -V #

Use -V (verify) to check whether files have changed since installation.

rpm -V httpd   # verify the integrity of a specific package
rpm -Va        # verify all packages

Empty output means no changes; if there are changes, each line is annotated with flags indicating which attributes changed.

FlagMeaning
SFile size changed
MPermissions (mode) changed
5MD5 checksum changed (content changed)
TModification time (mtime) changed
cThis file is a config file

For example, S.5....T. c /etc/httpd/conf/httpd.conf means the config file’s size, content, and time changed. If you edited the config yourself, that’s a natural result.

Installing a local rpm file #

You can install a local file with dnf too, and this way is safer because it handles dependencies as well.

dnf install ./mypackage-1.0.rpm   # automatic dependency resolution
rpm -ivh mypackage-1.0.rpm        # no dependency resolution

Where possible, install with dnf to avoid dependency problems.

Exam points #

  • Adding a specific repository and installing from it is a staple question. Create a .repo file in /etc/yum.repos.d/, specify baseurl and gpgcheck=0, confirm it’s recognized with dnf repolist, and install.
  • Adding a repository is also possible with dnf config-manager --add-repo URL, but for a question that has you specify baseurl directly, writing the .repo file by hand is more precise.
  • Installing and switching module streams also comes up often. Handle enable and install with the single line dnf module install name:stream, and when changing the version, reinstall after dnf module reset.
  • Use dnf provides path to find the source package of a command or file. When a needed command is missing, trace back the package to install this way.
  • Don’t mix up the direction of rpm -qf (package from a file) and rpm -ql (files from a package).
  • A package install takes effect immediately and persists across reboots, but verify that the repository configuration remains on disk as a .repo file.

Wrap-up #

What this post locked in:

  • dnf is the higher-level tool that resolves dependencies automatically, while rpm is the low-level tool for handling individual files.
  • dnf basic commands. install, remove, update, search, info, provides, groups with group install, and history rolled back with history undo.
  • Repositories are managed with .repo files in /etc/yum.repos.d/, specifying baseurl and gpgcheck. For a local path, use file://.
  • AppStream modules pick a version with stream and profile. Install with dnf module install name:stream, and switch by reinstalling after reset.
  • rpm queries. Check install state and integrity with -qa, -qf, -ql, -V.

Next: system operations #

Now that we’ve put software on with packages, next we cover the tools for operating that system.

In #9 System operations: chronyd, journald, cron, systemd timer, tuned, we’ll synchronize time with chronyd, view logs with journald, schedule jobs with cron and systemd timer, and apply performance profiles with tuned — typing it all out firsthand as we go.

X