skip to content

dnf

The Fedora and RHEL package manager: RPM-based install and upgrade, repository configuration and priorities, modules and streams, transaction history, and how it superseded yum. Interviewers ask because dnf history undo and correct repository setup are how you recover a host after a bad update.

on this pageshow

questions

5

On a RHEL or Fedora host, a `dnf upgrade` run an hour ago has left a service broken. How do you find out exactly what that transaction changed, how do you reverse it, and what makes the reversal fail?

level: middleimportance: must knowfreq 64%

answer

  1. every transaction is recorded locally
  2. there is a transaction ID
  3. info first, then undo
  4. the old RPMs must still be fetchable
  5. config files are not packages

basics

~20 s

dnf records every transaction locally. dnf history lists them with IDs, dnf history info <id> shows every package the transaction added, removed or upgraded, and dnf history undo <id> reverses it — provided the older RPMs are still obtainable.

solid answer

~50 s

Every dnf transaction is written to a local history database, which is dnf's real operational advantage here. I'd run `dnf history` to get the transaction ID, then `dnf history info <id>` to see the exact old-to-new version of every package it touched, and line that up against when the service started failing. To reverse it, `dnf history undo <id>` computes the inverse transaction: downgrade what was upgraded, remove what was installed, reinstall what was removed. `dnf history rollback <id>` is the bigger hammer — it undoes everything performed *after* that transaction. The catch is that undo has to obtain the older RPMs, and dnf deletes downloaded packages after a successful run by default while distro repositories usually publish only the newest build. On a fleet you solve that with versioned repository snapshots. And undo only reverses packages: it will not revert your config edits or data the new version already migrated.

code

bash · 12 lines
bash
# What ran, and what exactly did it touch?
dnf history
dnf history info last

# Reverse just that one transaction
sudo dnf history undo last

# Or return the package set to how it looked at transaction 40
sudo dnf history rollback 40

# Single package, leaving the rest of the transaction alone
sudo dnf downgrade httpd

go deeper

for a junior

Know that dnf keeps a record of what it has done, and be able to say that dnf history lists past transactions while dnf history info <id> shows the packages one of them changed.

for a middle

Explain the mechanics: undo reverses a single transaction, rollback reverses everything after one, and both are new transactions computed as the inverse of the old. Say plainly that undo must fetch the older package versions.

for a senior

Show that you have done this under pressure — correlate the transaction time with when the service broke, know that undo cannot revert config edits or data migrations, and name repository snapshots as the thing that makes rollback real on a fleet.

for a principal

Own the recovery model: decide whether package-level rollback is even your recovery strategy versus redeploying an immutable image, and what repository snapshotting and staged patch rings you fund so that every host can actually reach its previous known-good state.

## What dnf records, without being asked Every install, upgrade, downgrade, remove and reinstall that dnf performs is logged to a transaction history database on the machine — `/var/lib/dnf/history.sqlite` on dnf 4. Nothing has to be enabled for this; it is on by default and it is what makes a RHEL-family box meaningfully recoverable after a bad update. Each entry holds a monotonically increasing transaction ID, the command line that was typed, the user who ran it, start and end times, the completion status, and the before/after version of every package the transaction touched. ## Reading the history `dnf history` prints the list — ID, command line, date, the actions taken (install, upgrade, erase, downgrade) and how many packages were altered. `dnf history info 42` expands one transaction into the per-package detail you actually need: for each package, whether it was installed, upgraded or erased, and which exact version replaced which. You can name transactions relatively as well: `last` and `last-1`, `last-2` and so on, which is convenient when the damage was done minutes ago. Filtering helps when you know the suspect but not the transaction: `dnf history list openssl` shows only the transactions that touched that package. ```bash dnf history # what has been done to this box dnf history info last # exactly what the most recent run changed dnf history list httpd # every transaction that touched httpd ``` ## Reversing it `dnf history undo <id>` builds the inverse of a single transaction and runs it as a new transaction (which is itself recorded, so you can undo the undo — that is `dnf history redo`). `dnf history rollback <id>` is different and worth keeping straight: it undoes *all* transactions performed after the ID you name, returning the package set to the state it was in at that point. If several unrelated changes have happened since, rollback will drag them back too, so undo is usually the surgical choice. When only one package is at fault, skip history entirely: `dnf downgrade httpd` steps back one version, and `dnf install httpd-2.4.57-11.el9` pins an exact known-good build if the repository still carries it. ## Why the reversal fails in practice Three failure modes account for nearly every real case. **The old packages no longer exist.** dnf's default is not to keep downloaded RPMs after a successful transaction, and public distro repositories generally publish only the current build of each package. So the inverse transaction knows what version it wants and cannot fetch it. This is the single most common reason an interviewer is fishing for. The fix is architectural, not a flag: a mirror you control (`reposync` plus `createrepo_c`), or Satellite/Katello content views, where you can pin a fleet to a dated snapshot of the repository and therefore always have the previous versions on hand. **The dependency graph has moved on.** If something installed after the bad transaction depends on the newer version, the inverse transaction is unsolvable. dnf will say so rather than half-apply it; you then decide whether `--allowerasing` (letting it remove the blocker) is acceptable. **The kernel.** Kernels are install-only packages — dnf keeps several side by side rather than upgrading in place (`installonly_limit`, 3 by default). Undoing a transaction that installed a new kernel removes the package, but you are still running whatever kernel booted. Getting back to the old one is a reboot into the previous boot entry, not a dnf operation. ## What undo does not restore Undo operates on packages, and only on packages. It does not revert edits you made to a config file — RPM protects marked config files during an upgrade, leaving the vendor version alongside yours as a `.rpmnew` file (or saving yours as `.rpmsave`), and the downgrade plays the same game in reverse. It does not un-migrate a database schema the new version already upgraded, it does not restore data the new version rewrote, and it does not restart anything: after an undo you still have running processes using the code they loaded at start, so you restart the service yourself. ## The point of the question An interviewer asking this is checking whether you have actually recovered a host after a bad patch window, or only read that dnf has history. The strong answer names the exact commands, distinguishes undo from rollback, and then immediately says the part that only experience teaches: rollback is only as real as your ability to fetch yesterday's RPMs, so on anything you care about you snapshot the repository, not just the host.

  • Why does `dnf history undo` tend to work on a Satellite-managed fleet but fail on a host pointed straight at public repositories?
    Because undo must download the previous package versions, and public repositories normally publish only the newest build of each package. Satellite or Katello content views (or a local mirror built with `reposync` and `createrepo_c`) hold dated snapshots, so the older RPMs are still served. Without that, the history entry tells you precisely what to reverse and dnf still cannot fetch the artefacts to do it.
  • The bad transaction installed a new kernel. Does `dnf history undo` put you back on the old one?
    Not by itself. Kernels are install-only packages, so dnf keeps several installed rather than replacing one; undo removes the newly installed kernel package, but the machine keeps running whatever kernel it booted. Returning to the previous kernel is a reboot into the older boot entry. Undo is a package operation, and the running kernel is not something a package transaction can change.
  • What is the difference between `dnf history undo` and `dnf history rollback`?
    `undo <id>` reverses exactly that one transaction and leaves everything done since in place. `rollback <id>` reverses every transaction performed after the one named, returning the package set to its state at that point — so unrelated work done since gets pulled back too. Undo is the surgical option; rollback is for "put this machine back to Tuesday".

The history database is a ledger of package changes, not a filesystem snapshot: it can post the reversing entry, but only if the goods it needs to put back are still in the warehouse.

saying these in an interview costs you the question

  • Describing dnf history as a filesystem or VM snapshot
  • Assuming undo restores config files you edited
  • Believing the previous RPM versions are always still in the repo
  • Calling `dnf remove` of the new package a rollback
  • Thinking transaction history must be enabled first

context

open as a page

You push a new build of a package to your internal RPM repository, but on a RHEL 9 client `dnf install` still offers yesterday's version. What are the likely causes, and how do you make dnf see the new build?

level: juniorimportance: should knowfreq 52%

basics

~20 s

dnf works from cached repository metadata rather than contacting the repo on every command, so the client is usually reading a stale index. Force a refresh with dnf --refresh install or dnf clean metadata, and confirm the repo is enabled and its metadata was regenerated.

open as a page

On a RHEL 8 host, `dnf install nodejs` installs Node.js 10 but your application needs Node.js 20. Walk through how you inspect and switch the module stream with dnf, and explain why `dnf module reset` is usually part of it.

level: seniorimportance: should knowfreq 32%

basics

~20 s

RHEL 8 ships several runtime versions as module streams, and one is marked default. Inspect with dnf module list nodejs, then reset the module's stream selection, enable the stream you want, and sync the installed packages onto it — dnf module switch-to does all three.

open as a page

On a RHEL 9 host, `dnf upgrade` has installed patched openssl and glibc packages, but a scanner still reports the vulnerable versions in running processes. Why, and which dnf command tells you what to restart or whether to reboot?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Upgrading a package replaces files on disk; processes already running keep using the code they loaded at start-up, so they stay vulnerable until restarted. dnf needs-restarting lists those processes, -s maps them to systemd services, and -r says whether a reboot is recommended.

open as a page

On Fedora 41 and later the `dnf` command is DNF 5, while RHEL 9 still ships dnf 4. What changes for you as an operator, and what is most likely to break?

level: middleimportance: nice to knowfreq 24%

basics

~20 s

DNF 5 is a rewritten implementation on the libdnf5 stack, made the default dnf in Fedora 41. Everyday verbs and the .repo files are broadly unchanged; what breaks is automation built on dnf 4's Python API, its plugins, or its exact output format.

open as a page