YUM and DNF (RHEL/Fedora)
YUM and DNF are the package managers used on Red Hat-based Linux distributions — RHEL, CentOS Stream, Rocky Linux, AlmaLinux, and Fedora — the RPM-based counterparts to Debian's apt. They install, update, and remove software while automatically resolving dependencies, so you never have to hunt down libraries by hand. DNF ("Dandified YUM") is the modern successor to YUM: it has been Fedora's default since Fedora 22 (2015) and RHEL's default since RHEL 8. The two share almost identical command syntax, so learning one means you already know the other.
Overview / How YUM and DNF Work
Software on these distributions ships as RPM (Red Hat Package Manager) files — archives that bundle a program's files together with metadata: its name, version, and a list of other packages it depends on. The low-level tool that actually unpacks an RPM and records it in the system's package database (/var/lib/rpm) is rpm itself, but rpm does not know how to fetch packages over a network or resolve dependency chains. That is the job of YUM and DNF: they sit on top of rpm, talk to remote repositories (servers hosting collections of RPMs plus an index of what depends on what), and work out a consistent set of packages to install, upgrade, or remove.
YUM (Yellowdog Updater, Modified) was the original tool, written in Python, but its dependency resolver became slow and memory-hungry as repositories grew. DNF was built as its replacement: it uses libsolv, a fast SAT-based (satisfiability) solver — the same library used by openSUSE's zypper — to compute dependency solutions, and it exposes a stable API that other tools and plugins can build on. On RHEL 8+ and its clones, yum is literally a symlink to dnf, so old muscle memory keeps working even though DNF is doing the work underneath. On RHEL/CentOS 7 and older, only the original YUM exists.
Repositories
Each repository is defined by a .repo file under /etc/yum.repos.d/, an INI-style config listing a name, a URL (or mirror list) to fetch packages from, and whether GPG signature checking is required:
cat /etc/yum.repos.d/almalinux-baseos.repo
Output:
[baseos]
name=AlmaLinux $releasever - BaseOS
mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/baseos
baseurl=https://repo.almalinux.org/almalinux/$releasever/BaseOS/$basearch/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux
gpgcheck=1
enabled=1
DNF downloads and caches each enabled repository's metadata (package lists, dependency data, checksums) under /var/cache/dnf so it does not have to re-download it on every command. You can list what is currently enabled:
dnf repolist
Output:
repo id repo name
appstream AlmaLinux 9 - AppStream
baseos AlmaLinux 9 - BaseOS
epel Extra Packages for Enterprise Linux 9 - x86_64
Note that epel (Extra Packages for Enterprise Linux) is a community repository with thousands of extra packages that is not enabled by default on RHEL and its clones — you have to install the epel-release package yourself, which is a common source of "package not found" confusion for newcomers.
Syntax
Both tools follow the same general form:
dnf <command> [options] <package-name>
| Command | Purpose |
|---|---|
install |
Install one or more packages and their dependencies |
remove (alias erase) |
Uninstall a package; also removes packages left with nothing depending on them if you follow up with autoremove |
update / upgrade |
Upgrade installed packages to the latest available version (true synonyms in DNF; run with no package name to upgrade everything) |
search |
Search package names and summaries for a keyword |
info |
Show detailed metadata about a package |
list installed / list available |
List packages already installed, or installable from enabled repos |
provides |
Find which package provides a given file or command |
history |
Show past transactions, and undo/redo them |
clean all |
Delete cached package files and metadata |
makecache |
Force-refresh repository metadata immediately |
autoremove |
Remove packages that were pulled in as dependencies but are no longer needed |
-y |
Assume "yes" to all prompts (needed for non-interactive scripts) |
Examples
Example 1: Installing a package
sudo dnf install httpd
Output:
Last metadata expiration check: 0:12:34 ago on Tue Aug 4 09:15:02 2026.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
httpd x86_64 2.4.57-2.el9 appstream 1.5 M
Installing dependencies:
apr x86_64 1.7.0-11.el9 appstream 125 k
apr-util x86_64 1.6.1-20.el9 appstream 97 k
Transaction Summary
================================================================================
Install 3 Packages
Total download size: 1.7 M
Installed size: 4.6 M
Is this ok [y/N]: y
Running transaction
Preparing : 1/1
Installing : apr-1.7.0-11.el9.x86_64 1/3
Installing : apr-util-1.6.1-20.el9.x86_64 2/3
Installing : httpd-2.4.57-2.el9.x86_64 3/3
Verifying : httpd-2.4.57-2.el9.x86_64 1/3
Installed:
httpd-2.4.57-2.el9.x86_64 apr-1.7.0-11.el9.x86_64 apr-util-1.6.1-20.el9.x86_64
Complete!
DNF resolved httpd's two dependencies automatically, showed a transaction summary with download and install sizes, waited for confirmation, then downloaded and installed all three RPMs. To actually start the web server and have it launch on boot, you would follow up with sudo systemctl enable --now httpd.
Example 2: Searching, inspecting, and removing a package
dnf search "text editor"
Output:
============================ Name & Summary Matched: text, editor ============================
nano.x86_64 : A small text editor
vim-enhanced.x86_64 : A version of the VIM editor which includes recent enhancements
emacs.x86_64 : GNU Emacs text editor
dnf info nano
Output:
Installed Packages
Name : nano
Version : 6.2
Release : 1.el9
Architecture : x86_64
Size : 803 k
Source : nano-6.2-1.el9.src.rpm
Repository : @System
Summary : A small text editor
URL : https://nano-editor.org
License : GPLv3+
Description : GNU nano is a small and friendly text editor.
sudo dnf remove nano
Output:
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Removing:
nano x86_64 6.2-1.el9 @System 803 k
Transaction Summary
================================================================================
Remove 1 Package
Is this ok [y/N]: y
Running transaction
Preparing : 1/1
Removing : nano-6.2-1.el9.x86_64 1/1
Verifying : nano-6.2-1.el9.x86_64 1/1
Removed:
nano-6.2-1.el9.x86_64
Complete!
dnf search matches keywords in package names and summaries, dnf info shows full metadata for a specific package, and dnf remove uninstalls it — DNF only removes what you asked for here, since nothing else on the system depends on nano.
Example 3: Reviewing and undoing a transaction
sudo dnf history
Output:
ID | Command line | Date and time | Action(s) | Altered
-------------------------------------------------------------------------------
4 | remove nano | 2026-08-04 09:32 | Removed | 1
3 | install nano | 2026-08-04 09:20 | Install | 1
2 | update | 2026-08-04 08:55 | Update | 14
1 | install httpd | 2026-08-04 08:40 | Install | 3
sudo dnf history undo 4
Output:
Transaction ID : 4
Begin time : 2026-08-04 09:32
Begin rpmdb : ...
End time : 2026-08-04 09:32
End rpmdb : ...
User : root
...
Install 1 Package
Is this ok [y/N]: y
Complete!
Every transaction DNF performs is logged with an ID. dnf history undo <ID> reverses exactly that transaction — here it reinstalls nano, the package removed in transaction 4 — which is far safer than trying to manually remember and redo commands after a mistake.
How DNF Resolves and Applies a Transaction, Step by Step
When you run sudo dnf install httpd, several things happen in order:
- Metadata freshness check: DNF checks whether the cached repository metadata under
/var/cache/dnfis older than the configured expiry (commonly a few hours); if it is stale, it re-downloads the package lists and dependency data from each enabled repo. - Candidate lookup: DNF searches all enabled repositories for packages named (or matching)
httpd, along with the versions of everything already installed on the system. - Dependency solving: The candidates and the currently-installed package set are handed to the libsolv SAT solver, which computes a consistent set of packages to add, upgrade, or remove that satisfies every dependency and conflict constraint — this is what pulls in
aprandapr-utilautomatically. - Transaction summary and confirmation: DNF prints the packages it plans to touch along with download and installed sizes, and waits for a
y/Nanswer (skipped entirely if you passed-y). - Download and verification: The chosen RPM files are downloaded into the cache and their GPG signatures are checked against imported keys, unless
gpgcheck=0is set in the repo file (not recommended). - RPM install: Control passes to the underlying
rpmlibrary, which unpacks each package's files onto the filesystem, runs any pre/post-install scriptlets (e.g. creating a system user, reloading systemd), and records the package in the RPM database at/var/lib/rpm. - History logging: The whole transaction is written to DNF's history database so it can be reviewed or undone later with
dnf history.
Common Mistakes
Mistake 1: Leaving a wildcard unquoted
Wrong:
dnf install httpd*
Bash expands httpd* against files in your current directory before DNF ever sees it. If a file named httpd.conf happens to be sitting in your working directory, you might end up asking DNF to install a package literally called httpd.conf, which fails or does the wrong thing. Quote the argument so DNF's own glob matching against repository package names is used instead:
sudo dnf install "httpd*"
Mistake 2: Bypassing DNF with raw rpm commands
Wrong:
sudo rpm -e httpd
rpm -e removes a package directly from the low-level database without DNF's dependency resolution. If something else on the system depends on httpd, this can leave the system in a broken, inconsistent state (or simply refuse to run, depending on the dependency). Let DNF handle removal so it can work out the full, correct set of changes:
sudo dnf remove httpd
Mistake 3: Assuming every package is in the base repos
Wrong:
sudo dnf install btop
Output:
No match for argument: btop
Error: Unable to find a match: btop
Many popular packages (like the btop system monitor) live in the community-maintained EPEL repository, which is not enabled by default on RHEL and its clones. Enable it first, then install:
sudo dnf install epel-release
sudo dnf install btop
Best Practices
- Always let
dnf(not rawrpm) handle installs and removals so dependencies stay consistent. - Read the transaction summary before confirming, especially the list of packages being removed — a dependency conflict can sometimes pull in more removals than you expect.
- Keep
gpgcheck=1in every repo file; disabling signature checking removes a real security guarantee. - Use
dnf historyto audit what changed on a system anddnf history undo <ID>to cleanly reverse a bad transaction instead of trying to manually reinstall or remove packages. - Run
dnf clean allordnf makecacheif metadata seems stale (e.g. a package you know exists isn't showing up in search). - Enable
epel-releaseexplicitly rather than guessing why an install fails with "no match". - Run
dnf autoremoveperiodically to clear out orphaned dependency packages left behind by earlier removals. - In scripts, use
-ydeliberately and sparingly — know exactly what a command will do before automating away the confirmation prompt. - For scheduled, unattended updates, use the dedicated
dnf-automaticpackage rather than a cron job that blindly runsdnf update -y.
Practice Exercises
- Install the
nginxpackage with DNF, then usesystemctl status nginxto check whether it is running. If it isn't, start and enable it. - Search for a package related to "json" processing, view its full details with
dnf info, then remove it again once you've confirmed what it does. - Run
dnf historyto see your last few transactions, pick one, and practice undoing it withdnf history undo <ID>. Then checkdnf historyagain to confirm the undo itself was logged as a new transaction.
Summary
- YUM and DNF are the package managers for RPM-based distributions (RHEL, CentOS, Rocky, AlmaLinux, Fedora); DNF is the modern successor and
yumis a symlink to it on RHEL 8+. - Repositories are defined in
/etc/yum.repos.d/*.repofiles; DNF caches their metadata locally and refreshes it periodically. - Core commands:
install,remove,update/upgrade,search,info,list,history. - DNF uses the libsolv SAT solver to compute a consistent set of packages before showing a transaction summary and asking for confirmation.
- Every transaction is logged and can be reversed with
dnf history undo <ID>. - Common pitfalls: unquoted wildcards being expanded by the shell, bypassing DNF with raw
rpmcommands, and assuming a package is available without enabling EPEL. - Prefer DNF over
rpmdirectly, keep GPG checking on, and usednf-automaticinstead of hand-rolled cron scripts for unattended updates.
