This is the process for patching a Red Hat Enterprise Linux server, written as commands in the order you run them. It applies to RHEL 8, 9 and 10 and, unchanged, to Rocky Linux and AlmaLinux, because all of them use dnf and publish security advisories in the same format. It ends with how to automate the routine and where a single host’s process stops being enough for a fleet.
The commands at a glance
| Step | Command | What it tells you or does |
|---|---|---|
| 1. Check the subscription and repos | subscription-manager status, dnf repolist | Whether the host can see updates at all |
| 2. List pending security advisories | dnf updateinfo list --security | Each RHSA and the package it fixes |
| 3. Apply security updates only | dnf upgrade --security | Installs fixes for published advisories |
| 4. Patch one CVE or advisory | dnf upgrade --cve CVE-… / --advisory RHSA-… | A targeted fix ahead of the window |
| 5. Check for a reboot | dnf needs-restarting -r | Exit 1 if the kernel or a core library changed |
| 6. Record or undo the change | dnf history, dnf history undo <id> | The audit record and the rollback |
| 7. Automate it | dnf-automatic-install.timer | The same steps on a schedule |
Step 1: Confirm the host can see updates
A RHEL server that is not registered, or whose repositories are disabled, reports “nothing to do” and looks fully patched. Check before you trust any later output:
sudo subscription-manager status # "Overall Status: Registered" (or Simple Content Access)
sudo dnf repolist # BaseOS and AppStream must be listed
sudo dnf makecache # refresh metadata now instead of waiting for the timer
On Rocky Linux and AlmaLinux there is no subscription step; dnf repolist is enough. Hosts behind a proxy or pointed at an internal mirror are the usual source of stale results, so check that the mirror itself was synced recently.
Step 2: See what is pending, by severity
dnf reads Red Hat’s advisory metadata (updateinfo), which tags every update as a security advisory (RHSA), a bug fix (RHBA) or an enhancement (RHEA), each with a severity.
sudo dnf updateinfo summary # counts by type and severity
sudo dnf updateinfo list --security # every pending security advisory
sudo dnf updateinfo list --security --sec-severity=Critical
sudo dnf updateinfo info RHSA-2026:1234 # the advisory text, CVEs and packages
sudo dnf check-update --security; echo $? # exit 100 when updates are pending
The exit code of dnf check-update is the one to use in scripts and monitoring: 100 means updates are available, 0 means none, 1 means an error.
Step 3: Apply security updates only
sudo dnf upgrade --security -y
This installs every package that fixes a published security advisory and leaves bug-fix and enhancement updates for the next full maintenance window. Two variations matter:
dnf upgrade-minimal --securitymoves each package only to the version that fixes the advisory, not to the newest build in the repository. It is the most conservative option for production systems in a change freeze.dnf upgrade --security --sec-severity=Critical --sec-severity=Importantlimits the run to the two severities most patch policies set deadlines for.
Run the full dnf upgrade on a monthly cadence anyway. Security-only patching keeps the host safe between windows, but a host that never takes bug fixes drifts away from what the vendor tests, and the next security fix eventually depends on a bug fix you skipped.
Step 4: Patch one CVE ahead of the window
When a single CVE is in the news, you do not need to wait for the monthly run:
sudo dnf updateinfo info --cve CVE-2026-12345 # which advisory fixes it, if any
sudo dnf upgrade --cve CVE-2026-12345 -y # apply just that fix
sudo dnf upgrade --advisory RHSA-2026:1234 -y # or by advisory ID
If updateinfo finds nothing, Red Hat has either not shipped a fix yet or rated the CVE as not affecting RHEL. The Red Hat CVE page for that ID states which, and is the evidence an auditor will ask for.
Step 5: Decide whether the host needs a reboot
sudo dnf needs-restarting -r; echo $? # 1 = reboot required, 0 = not required
sudo dnf needs-restarting -s # services still running old libraries
-r checks the packages whose update only takes effect at boot: the kernel, glibc, systemd, the linux-firmware and a few others. If it returns 0 but -s lists services, a systemctl restart of those services finishes the job without downtime. On RHEL 7 the same command ships in yum-utils as needs-restarting -r.
For kernel CVEs on hosts that cannot reboot on short notice, RHEL’s kernel live patching applies the fix to the running kernel:
sudo dnf install kpatch-dnf
sudo dnf kpatch auto # subscribe to live patches for every installed kernel
sudo kpatch list # what is loaded now
Live patches cover selected Critical and Important kernel CVEs for a limited time per kernel build. They buy time until the next planned reboot; they do not replace it.
Step 6: Keep the record and know how to undo it
Every dnf transaction is recorded on the host:
sudo dnf history list --reverse | tail # transaction IDs, dates and who ran them
sudo dnf history info 42 # packages and versions in transaction 42
sudo dnf history undo 42 # roll transaction 42 back
dnf history undo works when the previous package versions are still available in the repositories, which is true for RHEL’s own repos and most mirrors. For a package you need to keep at a known version, pin it instead of undoing it every week:
sudo dnf install python3-dnf-plugin-versionlock
sudo dnf versionlock add openssl # pin the installed version
sudo dnf versionlock list
sudo dnf versionlock delete openssl # release the pin later
Write the undo command for your riskiest package into the change ticket before you patch. At 2am you will not want to work it out.
Step 7: Automate it with dnf-automatic
dnf-automatic runs steps 2 and 3 on a systemd timer.
sudo dnf install dnf-automatic
sudo vi /etc/dnf/automatic.conf
[commands]
upgrade_type = security # "default" applies every update
apply_updates = yes
random_sleep = 3600 # spread hosts out so the mirror is not hit at once
[emitters]
emit_via = motd # or "email" with the [email] section filled in
sudo systemctl enable --now dnf-automatic-install.timer
systemctl list-timers 'dnf-automatic*'
Choose the timer by what you want it to do, because the names are easy to confuse: dnf-automatic-install.timer downloads and installs, dnf-automatic-download.timer only downloads, dnf-automatic-notifyonly.timer only reports, and plain dnf-automatic.timer follows apply_updates in the config file. A common pattern is the install timer with upgrade_type = security on every host, and full upgrades kept for the monthly window.
What dnf-automatic does not do: it never reboots, it does not stagger rollouts between hosts, and its record of what happened lives on each host. That is fine for five servers. It is the point where most teams add a Linux patch management tool on top.
From one host to a fleet
The steps above patch one host well. Across fifty, the questions change: which hosts still have the advisory pending, which ones need a reboot, which ran the update and which failed, and can QA take it a day before production. The three usual answers:
| Approach | Good at | Where it stops |
|---|---|---|
dnf-automatic on every host | Free, already installed, security-only by config | No central view, no staging, no reboot coordination |
Ansible playbooks wrapping dnf | Batching with serial, reboots with the reboot module | You build and keep the reporting, CVE context and history |
| Red Hat Satellite | Content views, lifecycle environments, Red Hat support | RHEL-family hosts only; a server to run; see Satellite alternatives |
| A cross-distro tool such as SysWard | One view of every host and CVE, grouped rollouts, history | Agent per host; no repository mirroring or content views |
SysWard runs the same commands described here. Its agent reads dnf’s security metadata to separate security updates from the rest, applies upgrades from a schedule or on demand, pins packages with versionlock, and reports needs-restarting -r so the dashboard shows which hosts are waiting for a reboot. The Red Hat patch management guide covers the fleet side, and the same workflow runs for Rocky Linux and Ubuntu or SUSE hosts in the same console.
A monthly RHEL patching checklist
- Confirm every host is registered and its repositories are current (step 1).
- Export pending security advisories by severity and attach them to the change ticket (step 2).
- Patch a staging group, run your smoke tests, wait a day.
- Apply
dnf upgrade(or--securityin a freeze) to production in batches (step 3). - Reboot the hosts
needs-restarting -rflags, inside the window (step 5). - Save
dnf historyoutput, or your tool’s report, as evidence (step 6). - Leave
dnf-automaticon for security updates between windows (step 7).
If you also run SUSE hosts, the SUSE patching process with zypper is the same checklist with the zypper commands. To see every RHEL, Rocky and Alma host’s pending advisories in one place, start free with 5 agents, no card required.