Managing Packages with dnf: A Practical Guide for RHEL-Family Linux
Learn the dnf commands you'll actually use on a RHEL-family VPS - installing, removing, updating, searching, undoing mistakes, and automating security updates.
1 October 2024 6 min read
If you’ve just provisioned a VPS running AlmaLinux, Rocky Linux, Oracle Linux, VzLinux, Fedora, or any other RHEL-family distribution, dnf is the tool you’ll use to install, update, and remove software. It’s the successor to yum, and if you’ve used yum before, most of the commands will feel familiar – dnf is largely a drop-in replacement with better dependency resolution and a few extra features worth knowing about.
This guide covers the dnf commands you’ll actually use day to day: installing and removing packages, searching for software, keeping the system updated, undoing a bad update, and setting up automatic patching so you’re not doing this by hand every week.
Installing and removing packages
To install a package, use dnf install followed by the package name:
sudo dnf install nginx
You can install several packages in one go:
sudo dnf install nginx git wget unzip
To remove a package, use dnf remove. This also removes any dependencies that were pulled in for it and aren’t needed by anything else:
sudo dnf remove nginx
After removing packages, it’s worth cleaning up any leftover dependencies that dnf couldn’t remove automatically at the time (this happens if a package was installed as a dependency of something else that’s since been removed):
sudo dnf autoremove
Searching for packages
If you’re not sure of the exact package name, search for it:
dnf search postgresql
dnf search matches against package names and summaries. If you want to search descriptions too, add all:
dnf search all postgresql
To see detailed information about a specific package before installing it – version, size, description, source repo – use dnf info:
dnf info nginx
If you need to find out which package provides a particular file or command (useful when a program complains a binary or library is missing), use dnf provides:
dnf provides */ifconfig
Checking what’s installed
To list all installed packages:
dnf list installed
To check whether a specific package is installed, pipe that through grep:
dnf list installed | grep nginx
To see what’s available but not installed:
dnf list available
Updating the system
To see what updates are available without installing them:
dnf check-update
To update everything on the system:
sudo dnf update
dnf upgrade is an alias for the same thing on modern dnf – the two are interchangeable. On a fresh unmanaged VPS, running this regularly is the single most important thing you can do for security. Kernel and OpenSSL updates in particular shouldn’t sit unapplied for weeks.
To update just one package:
sudo dnf update nginx
If a kernel update was applied, you’ll need to reboot for it to take effect:
sudo reboot
Undoing a transaction with dnf history
Every dnf operation that changes the system gets logged as a transaction. This is one of dnf’s most useful features, because it means an update that breaks something isn’t necessarily a disaster.
To see the transaction history:
dnf history
You’ll get output like this:
ID | Command line | Date and time | Action(s) | Altered
-------------------------------------------------------------------------------
12 | update | 2026-08-20 09:14 | Update | 6
11 | install nginx | 2026-08-18 16:02 | Install | 3
10 | remove httpd | 2026-08-15 11:47 | Removed | 1
To see exactly what a specific transaction did:
dnf history info 12
If a transaction caused a problem, undo it with dnf history undo and the transaction ID:
sudo dnf history undo 12
This reverses that specific transaction: packages it installed get removed, packages it removed get reinstalled, and packages it updated get downgraded to their previous version. If you want to reverse everything from a certain point forward – not just one transaction – use dnf history rollback instead:
sudo dnf history rollback 10
This undoes everything that happened after transaction 10, leaving the system in the state it was in immediately after transaction 10 completed. One important caveat: neither command reliably downgrades core system packages like the kernel, glibc, or SELinux policy packages – for those, you’re better off restoring from a snapshot or backup.
Automating updates with dnf-automatic
On an unmanaged VPS, nobody is going to log in and run dnf update for you. dnf-automatic is the official tool for handling this on a schedule, using a systemd timer rather than a cron job.
Install it first, since it’s a separate package from dnf itself:
sudo dnf install dnf-automatic
Its behaviour is controlled by /etc/dnf/automatic.conf. By default, dnf-automatic only downloads updates and emails a notification – it does not install anything until you tell it to. To have it actually apply updates, edit the config file and set:
[commands]
apply_updates = yes
There are three timer units available, depending on how hands-off you want to be:
dnf-automatic-notifyonly.timer– checks for updates and notifies you, installs nothingdnf-automatic-download.timer– downloads updates so they’re ready, but doesn’t install themdnf-automatic-install.timer– downloads and installs updates automatically (requiresapply_updates = yesabove)
Enable and start the one that matches how much automation you want. For most unmanaged VPS setups, fully automatic installation is the sensible default:
sudo systemctl enable --now dnf-automatic-install.timer
You can check it’s scheduled correctly with:
systemctl list-timers dnf-automatic-install.timer
By default, dnf-automatic runs once a day at a randomised time (to avoid every server on the internet hitting the mirrors at the same second). If you’d rather review updates before they land on a production box, use the download-only timer and apply them manually once you’ve checked what changed.
Working with package groups
Groups let you install a bundle of related packages in one command – useful for things like “Development Tools” rather than installing a compiler toolchain piece by piece. List the available groups:
dnf group list
Install one:
sudo dnf group install "Development Tools"
See what’s in a group before installing it:
dnf group info "Development Tools"
Managing repositories
dnf pulls packages from configured repositories. To see which ones are enabled:
dnf repolist
To include disabled repositories in the listing too:
dnf repolist --all
Third-party software (Docker, Nginx’s own repo, etc.) is usually distributed as a .repo file dropped into /etc/yum.repos.d/, or via a setup script from the vendor. Only add repositories from sources you trust – a malicious or compromised repo has the same access to your system as a root shell.
A quick reference
| Task | Command |
|---|---|
| Install a package | dnf install |
| Remove a package | dnf remove |
| Search for a package | dnf search |
| Show package info | dnf info |
| List installed packages | dnf list installed |
| Check for updates | dnf check-update |
| Update everything | dnf update |
| View transaction history | dnf history |
| Undo one transaction | dnf history undo |
| List repositories | dnf repolist |
That covers what you’ll need for day-to-day package management on a RHEL-family server. Once updates are handled, the next thing worth locking down is the firewall – see our guide to firewalld basics for opening the ports your services actually need.