Managing Packages with yum and dnf
With CentOS 8 out, dnf is now the package manager on the current release while yum remains on the CentOS 7 machines most of us still run in production. On CentOS 8, yum is a symlink to dnf and most commands work identically, but a few things changed in ways that matter for a server admin: modules (AppStream), how history and rollback work, and how you pin a version. I switch between the two all week, so these are my notes on daily operations, with the differences flagged.
Search, inspect, install
These behave the same on both versions:
yum search mariadb
yum info mariadb-server
yum provides */semanage
yum install mariadb-server
yum remove mariadb-server
provides is the one people forget: when a command is missing, it tells you which package to install. On CentOS 8, dnf provides works but there is also dnf repoquery --whatprovides.
Install a specific version when several are available:
yum list --showduplicates nginx
yum install nginx-1:1.16.1-1.el7.ngx
Extra repositories
EPEL is the first repo on any CentOS box. On CentOS 7 it comes from the extras repository; on CentOS 8 the same package name works:
yum install epel-release
For third-party repositories you want available but not active by default, install them and then flip them on per command:
yum-config-manager --disable remi-php72 # CentOS 7 (yum-utils)
yum --enablerepo=remi-php72 install php-fpm
dnf config-manager --set-disabled remi-php72 # CentOS 8
I keep optional repos disabled by default. That prevents an update from pulling a whole PHP stack from a repo you only wanted one package from. Check what is active with yum repolist and everything including disabled with yum repolist all.
AppStream modules (CentOS 8 only)
This is the main new concept. Some software ships in several parallel streams, and you choose one before installing:
dnf module list mariadb
dnf module list php
dnf module enable php:7.3
dnf install php-fpm
dnf module info php
Switching a stream later requires a reset first:
dnf module reset php
dnf module enable php:7.2
dnf distro-sync php\*
If you try to install a package from a different stream without resetting, dnf refuses with a conflicts error rather than silently mixing versions. Modules do not exist on CentOS 7; there you get whatever the repo ships or use a third-party repo like Remi or SCL for alternative versions.
Updating without surprises
yum check-update
yum update
yum update --security # CentOS 7 needs yum-plugin-security; dnf has it built in
yum update kernel
Exclude packages you manage separately, either per command or permanently. Per command:
yum update --exclude=mariadb\*
Permanently, in /etc/yum.conf (CentOS 7) or /etc/dnf/dnf.conf (CentOS 8):
exclude=mariadb* kernel*
For stronger pinning of an installed version, the versionlock plugin works the same on both:
yum install yum-plugin-versionlock # CentOS 7
dnf install python3-dnf-plugin-versionlock # CentOS 8
yum versionlock add mariadb-server
yum versionlock list
yum versionlock delete mariadb-server
After updates, find out whether anything running needs a restart. needs-restarting comes from yum-utils on both:
needs-restarting -r # reboot needed?
needs-restarting -s # services needing restart (CentOS 8 dnf-utils)
History and undo
Every transaction is recorded:
yum history list
yum history info 42
yum history undo 42
undo reverses a transaction (removes what was installed, reinstalls what was removed) if the old package versions are still available in the repos or cache. This is what saved me when a yum update picked up a broken PHP build: history info showed exactly which packages changed, history undo put them back. On CentOS 8 the output format differs slightly but the commands are the same.
Cleaning up
yum autoremove # remove orphaned dependencies
yum clean all # drop cached metadata and packages
package-cleanup --oldkernels --count=2 # CentOS 7, from yum-utils
dnf remove --oldinstallonly --setopt installonly_limit=2 kernel # CentOS 8
On CentOS 8, installonly_limit=3 in dnf.conf already caps how many kernels are kept; on CentOS 7 the same option lives in yum.conf and is also 3 by default. Also on CentOS 8, dnf caches metadata via a systemd timer (dnf-makecache.timer) rather than the yum-cron package; for automatic updates install dnf-automatic and enable dnf-automatic-install.timer.
Quick checks after a change
yum repolist
rpm -qa --last | head
yum history list | head
dnf module list --enabled # CentOS 8
rpm -V nginx
rpm -qa --last lists recently installed packages with timestamps, which is a quick way to confirm what an update actually touched. rpm -V reports files in a package that differ from what was shipped, useful when you suspect a config file was clobbered.
Errors
Error: Failed to download metadata for repo 'AppStream'(CentOS 8) orCannot find a valid baseurl for repo: base/7/x86_64(CentOS 7): DNS or proxy problem, or a mirror list outage. Checkcurl -I http://mirrorlist.centos.organd anyproxy=setting in the config.Transaction check error: file /usr/lib64/... conflicts between attempted installs of ...: two repositories provide the same package. Addpriority=viayum-plugin-priorities(7) or useexclude=on the offending repo section.Error: Problems in request: broken groups or modules: php(CentOS 8): stream mismatch after a manual repo install.dnf module reset phpand start again.Existing lock /var/run/yum.pid: another copy is running as pid 1234: usuallyyum-cronor PackageKit. Wait, orkillit if it is genuinely stuck.
Honestly, modules are the only part of 8 that made me stop and think. Everything else carries over from yum.