- linux
- l2
- topic-pack
- dnf --- Portal | Level: L2: Operations | Topics: DNF Package Manager | Domain: Linux
DNF Package Manager — Primer¶
Why This Matters¶
DNF is the default package manager on RHEL 8+, Fedora, CentOS Stream, Rocky Linux, and AlmaLinux.
If you manage Red Hat-family servers in production, every package install, security patch, and
compliance audit goes through dnf. Understanding its transaction model, module streams, and repo
management separates someone who can dnf install nginx from someone who can manage package
state across a fleet of 500 servers without surprises.
The existing package-management topic covers both apt and yum/dnf at a high level. This topic
goes deep on dnf-specific features: module streams, transaction history, versionlock, dnf automatic,
security-only updates, offline repos, and fleet patterns.
Core Concepts¶
1. DNF vs Yum — What Actually Changed¶
Name origin: DNF stands for Dandified Yum — literally "a fancier version of Yum." Yum itself stands for Yellowdog Updater, Modified — originally written for the Yellow Dog Linux distribution (a PowerPC Linux distro, 1999). DNF was created by Red Hat engineers starting in 2012 as a ground-up rewrite using libsolv (SUSE's dependency solver, written in C) instead of Yum's slow Python-based solver. DNF became the default on Fedora 22 (2015) and RHEL 8 (2019).
On RHEL 8+, yum is a symlink to dnf. Yum4 is dnf under the hood. The key differences
from legacy yum (yum3, RHEL 7):
| Feature | Yum3 (RHEL 7) | DNF / Yum4 (RHEL 8+) |
|---|---|---|
| Dependency solver | Custom (slow, sometimes wrong) | libsolv (fast, correct) |
| Module streams | Not available | Full support |
| Performance | Slow metadata parsing | C-based hawkey, much faster |
| Python API | yum module |
dnf module (incompatible) |
| Config compat | N/A | Reads yum.conf, yum.repos.d |
| Plugin API | yum plugins | dnf plugins (different API) |
If you have scripts that call yum, they still work on RHEL 8+ — but you should understand
you are running dnf. Old yum3 plugins will not work; they need dnf equivalents.
2. Repository Configuration¶
Repo files live in /etc/yum.repos.d/*.repo. Each file can define one or more [repo-id] sections.
[company-internal]
name=Company Internal Packages
baseurl=https://rpm.internal.company.com/el9/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-company
priority=10
sslverify=1
sslcacert=/etc/pki/tls/certs/company-ca.pem
Key fields:
baseurl/metalink/mirrorlist: Where to fetch packages. Use$releaseverand$basearchvariables for portability.gpgcheck=1: Always enable in production. Unsigned packages are a supply chain risk.
Gotcha: If you add a third-party repo and forget to import its GPG key, every
dnf installfrom that repo will fail with a "Public key not installed" error. Import keys before enabling repos:rpm --import https://repo.example.com/RPM-GPG-KEY-example. And never setgpgcheck=0in production — it silently disables signature verification, opening the door to tampered packages. -gpgkey: Path or URL to the GPG public key for signature verification. -priority: Requiresdnf-plugin-priorities(or built-in on some distros). Lower number = higher priority. Use to ensure internal repos override EPEL. -cost: Higher cost = less preferred. Default is 1000. Useful for slow mirrors. -enabled: 0 or 1. You can also toggle at runtime with--enablerepo/--disablerepo. -exclude: Space-separated list of package globs to never install from this repo. -module_hotfixes=1: Allow this repo to override module-stream-filtered packages (needed for some third-party repos).
List all configured repos and their status:
3. Module Streams and Profiles¶
Module streams solve the "which version of PostgreSQL?" problem. A single OS release can offer multiple versions of the same software simultaneously.
# List available modules
dnf module list
# List streams for a specific module
dnf module list postgresql
# Enable a stream (sticky — see footguns)
dnf module enable postgresql:15
# Install the default profile from the enabled stream
dnf module install postgresql:15
# Install a specific profile
dnf module install postgresql:15/server
# Check what's enabled
dnf module list --enabled
Key concepts:
- Module: A set of packages that belong together (e.g.,
postgresql). - Stream: A version track (e.g.,
15,16). Only one stream can be active per module. - Profile: A preset package list within a stream (e.g.,
server,client,devel).
Streams filter what packages are visible. When you enable postgresql:15, packages from the
:16 stream become invisible to the resolver. This prevents accidental version mixing.
Default trap: Once you enable a module stream, it is sticky. Switching streams (e.g.,
postgresql:15topostgresql:16) requiresdnf module reset postgresqlfollowed bydnf module enable postgresql:16. A directdnf module enable postgresql:16without reset will fail with a confusing "module stream is already enabled" error. This catches people during major version upgrades.Remember: Module stream workflow: "E-I-R-E" — Enable the stream, Install the profile, Reset when switching, Enable the new stream. Always
dnf module list --enabledto check what is active before making changes.
4. Transaction Model and History¶
Every dnf operation that changes packages is a transaction. DNF records every transaction
in an SQLite database at /var/lib/dnf/history.sqlite (RHEL 8) or /var/lib/dnf/history/ (RHEL 9+).
# List recent transactions
dnf history list
# Show details of a specific transaction
dnf history info 42
# Undo a single transaction (reverse its changes)
dnf history undo 42
# Rollback to the state before transaction 42
dnf history rollback 42
# Redo a previously undone transaction
dnf history redo 42
undo vs rollback:
undo 42reverses only transaction 42's changes.rollback 42reverses all transactions after 42, restoring the system to the state it was in right after transaction 42 completed.
This is the closest thing to a "package state snapshot" that RPM-based systems offer natively.
War story: A common fleet incident: someone runs
dnf updateon a production server and a new package version breaks the application. Withdnf history undo last, you can reverse the exact set of packages that were changed — rolling back to the previous working state without a full OS reinstall. This is why experienced ops engineers always checkdnf history listbefore and after maintenance windows.
5. Groups and Environments¶
Groups bundle related packages. Environments bundle groups.
# List available groups
dnf group list
dnf group list --hidden # includes hidden groups
# See what's in a group
dnf group info "Development Tools"
# Install a group
dnf group install "Development Tools"
# Install only mandatory + default packages (skip optional)
dnf group install --setopt=group_package_types=mandatory,default "Development Tools"
# Remove a group (removes packages unique to that group)
dnf group remove "Development Tools"
Groups track membership. If you install a group and a new package is later added to it,
dnf group upgrade will pick it up.
6. DNF Variables and Conditional Config¶
DNF supports variables in repo configs and the main config:
| Variable | Source | Example value |
|---|---|---|
$releasever |
OS release | 9 |
$basearch |
Architecture | x86_64 |
$arch |
Architecture (finer) | x86_64 |
| Custom vars | Files in /etc/dnf/vars/ |
Whatever you define |
Custom variables are useful for fleet management:
# Create a custom variable
echo "production" > /etc/dnf/vars/environment
# Use in repo config
# baseurl=https://rpm.internal.company.com/$environment/el$releasever/$basearch/
This lets you point dev, staging, and production servers at different repo paths using the same repo file, just by changing the variable file.
Quick Reference¶
# Search for packages
dnf search nginx
dnf provides '*/nginx.conf' # which package owns a file?
# Install / remove
dnf install nginx
dnf remove nginx
dnf reinstall nginx
# Update
dnf check-update # list available updates (exit 100 if updates exist)
dnf update # apply all updates
dnf update nginx # update specific package
dnf update --security # security patches only
# Info and queries
dnf info nginx # package details
dnf list installed # all installed packages
dnf repoquery --requires nginx # what does nginx need?
dnf repoquery --whatprovides '/etc/nginx/nginx.conf'
# History
dnf history list
dnf history undo last
# Modules
dnf module list
dnf module enable postgresql:15
dnf module install postgresql:15/server
# Cache
dnf clean all # wipe cached metadata + packages
dnf makecache # rebuild metadata cache
# Config inspection
dnf config-manager --dump # show effective config
Wiki Navigation¶
Prerequisites¶
- Linux Ops (Topic Pack, L0)
Related Content¶
- DNF Flashcards (CLI) (flashcard_deck, L1) — DNF Package Manager