Skip to content

rpm and dnf

rpm manages individual packages and queries the installed database; dnf resolves dependencies, talks to repositories and keeps a transaction history. RHEL 10 and Rocky 10 ship DNF 4 (dnf-4.20), and most daily work is a handful of queries.

Track: Core · Interview weight: Med


Must-Know Facts

Fact Value Verify with
Is it installed rpm -q <pkg> rpm -q bash
Package details rpm -qi rpm -qi openssh-server
Files, configs, docs rpm -ql, -qc, -qd rpm -qc openssh-server
Which package owns a file rpm -qf <path> rpm -qf /usr/bin/ls
Which package would provide a file dnf provides '*/<name>' dnf provides /usr/bin/dig
Verify installed files rpm -V (size, mode, digest, owner, mtime flags) sudo rpm -V openssh-server
Check a downloaded package rpm -K (signatures), rpm -qpl (files) rpm -K pkg.rpm
Install, remove, update dnf install, dnf remove, dnf upgrade dnf history
Undo a transaction dnf history undo <id> or last dnf history list
Updates available dnf check-update exits 100 echo $?
Security errata dnf updateinfo, dnf upgrade --security dnf updateinfo summary
Pin a version dnf versionlock add <pkg> (plugin) or exclude= in dnf.conf dnf versionlock list
Parallel kernels installonly_limit=3 keeps three grep installonly /etc/dnf/dnf.conf
Scriptlets and other queries rpm -q --scripts, --whatrequires; rpm -qp... on a package file rpm -q --scripts <pkg>
Backported fixes Changelog lists CVEs fixed in an old upstream version rpm -q --changelog <pkg>

Querying the rpm Database

rpm -q bash openssl-libs nosuchpkg
rpm -qa | wc -l
rpm -qi openssh-server | head -6

Output:

bash-5.2.26-6.el10.x86_64
openssl-libs-3.5.5-6.el10_2.x86_64
package nosuchpkg is not installed
513
Name        : openssh-server
Version     : 9.9p1
Release     : 25.el10_2.rocky.0.1
Architecture: x86_64
Install Date: Sat Aug 29 17:55:34 2026
Group       : Unspecified
rpm -qc openssh-server
rpm -qf /etc/ssh/sshd_config /usr/bin/ls
rpm -q --requires openssh-server | sort -u | head -6

Output:

/etc/pam.d/sshd
/etc/ssh/sshd_config
/etc/ssh/sshd_config.d/40-redhat-crypto-policies.conf
/etc/ssh/sshd_config.d/50-redhat.conf
/etc/sysconfig/sshd
openssh-server-9.9p1-25.el10_2.rocky.0.1.x86_64
coreutils-single-9.5-8.el10_2.x86_64
/bin/sh
/usr/bin/bash
/usr/sbin/useradd
config(openssh-server) = 9.9p1-25.el10_2.rocky.0.1
crypto-policies >= 20220824-1
libaudit.so.1()(64bit)

Verifying Installed Files

rpm -V compares files with the package database and prints only differences:

sudo chmod 644 /usr/bin/passwd
sudo rpm -V openssh-server shadow-utils
sudo chmod 4755 /usr/bin/passwd

Output:

S.5....T.  c /etc/ssh/sshd_config
.M.......    /usr/bin/passwd

The letters mark what differs: S size, M mode, 5 digest, U and G owner and group, T modification time, and c flags a configuration file.

A changed configuration file is normal; a changed binary (5 without c) is a finding. rpm -Va checks every package and is a quick integrity check after a suspected compromise, though an attacker with root can also alter the database.

Run rpm -V as root

As a normal user, files the user cannot read are reported as missing ... (Permission denied), which looks alarming and means nothing.


Installing and Removing with dnf

dnf --version | head -1
dnf -q info nginx | grep -E '^(Name|Version|Release|Repository|Summary)'
dnf -q provides /usr/bin/dig | head -3
sudo dnf -y install nginx
rpm -q nginx

Output:

4.20.0
Name         : nginx
Version      : 1.26.3
Release      : 6.el10_2.7
Repository   : appstream
Summary      : A high performance web server and reverse proxy server
bind-utils-32:9.18.33-15.el10_2.1.x86_64 : Utilities for querying DNS name servers
Repo        : appstream
Matched from:
# ... (trimmed)
nginx-1.26.3-6.el10_2.7.x86_64

Other everyday forms: dnf install ./pkg.rpm (local file with dependencies), dnf reinstall <pkg> (restores deleted files), dnf autoremove, dnf download <pkg>, dnf group list and dnf clean all.


Transaction History

sudo dnf history list | head -5
sudo dnf -y history undo last
rpm -q nginx
sudo dnf history info last | sed -n '1p;12,20p'

Output:

ID     | Command line             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
    11 | -y install nginx         | 2026-09-16 14:41 | Install        |    4 EE
    10 | install -y jq acl attr e | 2026-09-16 14:20 | I, U           |  181 EE
     9 | install -y cronie tldr   | 2026-09-16 13:33 | Install        |    7 EE
# ... (trimmed)
package nginx is not installed
Transaction ID : 12
Packages Altered:
    Removed logrotate-3.22.0-5.el10.x86_64              @@System
    Removed nginx-2:1.26.3-6.el10_2.7.x86_64            @@System
    Removed nginx-core-2:1.26.3-6.el10_2.7.x86_64       @@System
    Removed nginx-filesystem-2:1.26.3-6.el10_2.7.noarch @@System

history undo also removes pulled-in dependencies

The undo also removed logrotate, which transaction 11 had pulled in as a dependency. Noting the history ID before a risky upgrade gives an exact rollback target, as long as the repositories still carry the old versions.


Updates, Security and Pinning

dnf -q check-update | head -5
echo "rc=${PIPESTATUS[0]}"
dnf -q updateinfo summary
rpm -q --changelog openssl-libs | grep -m3 -E 'CVE-'
grep -E '^(installonly_limit|gpgcheck|exclude)' /etc/dnf/dnf.conf

Output:

dbus-broker.x86_64                     36-5.el10_2                     baseos   
expat.x86_64                           2.7.3-1.el10_2.3                baseos   
glib2.x86_64                           2.80.4-12.el10_2.22             baseos   
openssl-fips-provider.x86_64           1:3.5.8-1.el10_2                baseos   
rc=100
Updates Information Summary: available
    4 Security notice(s)
        1 Important Security notice(s)
        3 Moderate Security notice(s)
Fix CVE-2026-7383, CVE-2026-9076, CVE-2026-34180, CVE-2026-34181,
CVE-2026-34183, CVE-2026-42764, CVE-2026-42766, CVE-2026-42767, CVE-2026-42768,
CVE-2026-42769, CVE-2026-42770, CVE-2026-45445, CVE-2026-45446, CVE-2026-45447,
gpgcheck=1
installonly_limit=3

dnf check-update returns 100 when updates exist, 0 when there are none and 1 on error, which suits monitoring scripts. The changelog shows CVEs fixed in OpenSSL 3.5.5 without changing its upstream version.


Common Errors

sudo dnf -y install nosuchpackage

Output:

Last metadata expiration check: 1:17:54 ago on Wed Sep 16 13:24:01 2026.
No match for argument: nosuchpackage
Error: Unable to find a match: nosuchpackage

Error: Unable to find a match: nosuchpackage

Cause: no enabled repository has that name: a typo, a package in a disabled repository (EPEL, CRB), or a name that differs from the command (dig is in bind-utils).

Fix: dnf search, dnf provides '*/<command>', dnf repolist --all.

With a repository file that points to an unreachable host:

sudo dnf -y install tree 2>&1 | grep -E 'Error|Curl|broken'

Output:

Errors during downloading metadata for repository 'broken':
  - Curl error (6): Could not resolve hostname for https://repo.invalid/el10/repodata/repomd.xml [Could not resolve host: repo.invalid]
Error: Failed to download metadata for repo 'broken': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried

Error: Failed to download metadata for repo 'broken'

Cause: one enabled repository is unreachable (DNS, proxy, firewall, wrong URL), and dnf stops for all repositories.

Fix: curl -I <baseurl>; fix or disable the repository (sudo dnf config-manager --set-disabled broken), or add skip_if_unavailable=True to that repository.


Interview Checkpoints

L1: What is the difference between rpm and dnf?

Say first: rpm installs and queries individual package files without resolving dependencies; dnf resolves dependencies from repositories and records transactions.

Proof: rpm -ivh pkg.rpm fails on missing dependencies; dnf install ./pkg.rpm fetches them.

Follow-up: When is rpm still the right tool? (Queries and verification.)

L2: Find which package installed /etc/ssh/sshd_config and list its other config files.

Say first: query by file, then by package.

Proof: rpm -qf /etc/ssh/sshd_config; rpm -qc openssh-server

Follow-up: How do you find a package for a command that is not installed?

L2: Roll back yesterday's package update.

Say first: find the transaction and undo it.

Proof: sudo dnf history list; sudo dnf history undo <id>

Follow-up: What can prevent the undo from working?

L2: Keep the kernel from being updated while other packages update.

Say first: lock or exclude it.

Proof: sudo dnf versionlock add kernel-core, or sudo dnf upgrade --exclude='kernel*'

Follow-up: Why is a permanent kernel lock a risk?

L3: A scanner reports a CVE in openssl, but dnf says there is nothing to update.

Say first: check whether the installed build already contains the fix.

Proof: rpm -q --changelog openssl-libs | grep CVE-<id> and dnf updateinfo info --cve CVE-<id>.

Follow-up: How do you explain the finding to the security team?

L3: dnf install fails with Unable to find a match for a package the documentation names.

Say first: check repositories and the real package name.

Proof: dnf provides '*/htpasswd' shows httpd-tools; dnf repolist --all shows EPEL or CRB disabled.

Follow-up: How do you enable CRB on Rocky 10? (dnf config-manager --set-enabled crb.)


Captured on Rocky Linux 10.2 and Ubuntu 24.04.4 LTS (iximiuz Labs microVMs, kernel 6.1.167), 2026-09.