A package manager installs software together with its dependencies, keeps it updated from signed repositories and removes it cleanly. Debian and Ubuntu use APT with .deb packages, while Red Hat Enterprise Linux, Rocky Linux and AlmaLinux use DNF with .rpm packages; YUM is DNF's predecessor. This guide shows the everyday tasks side by side on Ubuntu 24.04 and Rocky Linux 9: updating, installing, searching, holding versions, adding third-party repositories, undoing changes and fixing common errors.
Prerequisites
To follow along you need:
- A server running Ubuntu 24.04 LTS (or Debian 12/13) and/or Rocky Linux 9 or AlmaLinux 9, for example a CubePath VPS.
- A non-root user with
sudoprivileges.
How APT, YUM and DNF relate
| Debian, Ubuntu | RHEL, Rocky Linux, AlmaLinux | |
|---|---|---|
| Package format | .deb | .rpm |
| High-level tool (resolves dependencies, uses repositories) | apt (also apt-get, apt-cache) | dnf (yum on EL7 and older) |
| Low-level tool (single package files, database queries) | dpkg | rpm |
| Repository configuration | /etc/apt/sources.list.d/ | /etc/yum.repos.d/ |
| Automatic updates | unattended-upgrades | dnf-automatic |
On Rocky Linux and AlmaLinux 8 and later, yum is only a compatibility link to dnf, so old yum commands keep working with the same syntax. You only meet the original YUM on CentOS 7 and other EL7 systems, which are end of life. This guide uses dnf throughout.
apt is the command meant for interactive use. apt-get and apt-cache do the same jobs with an output format that stays stable between versions, so prefer them in scripts.
Step 1 - Refreshing package information and updating the system
APT keeps a local copy of the package lists and needs to refresh it before installing or upgrading. apt upgrade then installs newer versions of installed packages:
sudo apt update
sudo apt upgrade
...
42 packages can be upgraded. Run 'apt list --upgradable' to see them.
apt upgrade never removes packages. When an update needs to remove or replace a package (common with kernel and major library updates), use full-upgrade instead:
sudo apt full-upgrade
DNF refreshes metadata automatically when it is older than its cache lifetime, so a single command lists and applies updates:
sudo dnf check-update
sudo dnf upgrade
On both families, a kernel update only takes effect after a reboot. Ubuntu creates /var/run/reboot-required when one is needed. On Rocky Linux, the needs-restarting command from the dnf-utils package tells you:
sudo dnf install dnf-utils
sudo needs-restarting -r
Core libraries or services have been updated since boot-up:
* kernel
Reboot is required to fully utilize these updates.
Step 2 - Searching for packages and reading their details
Search package names and descriptions:
apt search redis
dnf search redis
Show the version, repository, size, dependencies and description of a package before installing it:
apt show redis-server
dnf info redis
Package names differ between the two families. For example, the Apache web server is apache2 on Ubuntu and httpd on Rocky Linux, and the Redis server is redis-server versus redis. Searching first saves guesswork.
When you know the file or command you need but not the package, ask which package provides it. DNF can search all repositories directly:
dnf provides '*/bin/dig'
bind-utils-32:9.16.23-24.el9.x86_64 : Utilities for querying DNS name servers
Repo : appstream
On Ubuntu, install apt-file once and then search:
sudo apt install apt-file
sudo apt-file update
apt-file search bin/dig
Step 3 - Installing and removing packages
Install one or more packages. Both tools show what will be installed, including dependencies, and ask for confirmation:
sudo apt install nginx
sudo dnf install nginx
Add -y to skip the confirmation in scripts and automation.
To install a specific version, first list the versions available, then pin it in the install command:
apt list -a nginx
sudo apt install nginx=1.24.0-2ubuntu7
dnf list --showduplicates nginx
sudo dnf install nginx-1.20.1-20.el9
Use the exact version strings shown by the listing commands on your system; the ones above are only examples.
To install a package file you downloaded, pass its path. Using apt or dnf rather than dpkg -i or rpm -i means missing dependencies are fetched from the repositories:
sudo apt install ./package_name.deb
sudo dnf install ./package_name.rpm
Removing packages works differently on each family. On Ubuntu, remove keeps configuration files in /etc, purge deletes them too, and autoremove removes dependencies nothing needs any more:
sudo apt remove nginx
sudo apt purge nginx
sudo apt autoremove
On Rocky Linux, dnf remove also removes dependencies that were pulled in only for that package. Modified configuration files are kept with an .rpmsave extension:
sudo dnf remove nginx
Step 4 - Listing installed packages and their files
List installed packages, or check whether a specific one is installed:
apt list --installed nginx
dnf list --installed nginx
List the files a package installed, which is how you find its configuration files and binaries:
dpkg -L nginx
rpm -ql nginx
Find which installed package owns a file:
dpkg -S /usr/sbin/nginx
nginx: /usr/sbin/nginx
rpm -qf /usr/sbin/nginx
nginx-1.20.1-20.el9.x86_64
Show what a package depends on, and which installed packages depend on it:
apt-cache depends nginx
apt-cache rdepends --installed nginx
dnf repoquery --requires nginx
dnf repoquery --installed --whatrequires nginx
Step 5 - Holding a package at its current version
Sometimes a package must not be upgraded, for example a database server that you want to upgrade manually during a maintenance window. On Ubuntu, mark it as held:
sudo apt-mark hold postgresql-16
apt-mark showhold
postgresql-16
Release the hold later with sudo apt-mark unhold postgresql-16.
On Rocky Linux, use the versionlock plugin:
sudo dnf install python3-dnf-plugin-versionlock
sudo dnf versionlock add postgresql-server
sudo dnf versionlock list
Remove the lock with sudo dnf versionlock delete postgresql-server. Held packages do not receive security fixes either, so keep holds short and documented.
Step 6 - Adding a third-party repository
Software that is not in the distribution's repositories, or that you need in a newer version, usually comes from the vendor's own repository. The repository must be signed, and on Ubuntu the key must be tied to that repository only.
On Ubuntu 24.04, repositories are defined in /etc/apt/sources.list.d/. The steps below add the official Nginx repository as an example. Download the signing key into /etc/apt/keyrings:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/nginx.gpg
Create the repository definition in the deb822 format, with Signed-By pointing to that key so it cannot be used to sign packages from other repositories:
sudo nano /etc/apt/sources.list.d/nginx.sources
Types: deb
URIs: https://nginx.org/packages/ubuntu
Suites: noble
Components: nginx
Signed-By: /etc/apt/keyrings/nginx.gpg
Refresh the package lists and check that the new repository now provides the package:
sudo apt update
apt-cache policy nginx
The Version table in the output lists nginx.org as a source. Never use the deprecated apt-key command: it trusts a key for all repositories at once.
On Rocky Linux, repositories are .repo files in /etc/yum.repos.d/. Many projects ship a release package that installs the file and key for you. The most important one is EPEL, which adds thousands of extra packages; on Rocky Linux 9 it also needs the CRB repository:
sudo dnf install epel-release
sudo dnf config-manager --set-enabled crb
For a vendor repository, create the file yourself:
sudo nano /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
Check that it is enabled:
dnf repolist
repo id repo name
appstream Rocky Linux 9 - AppStream
baseos Rocky Linux 9 - BaseOS
extras Rocky Linux 9 - Extras
nginx-stable nginx stable repo
The first time you install a package from it, DNF shows the key fingerprint and asks you to import it. Compare it with the fingerprint published by the vendor before answering y.
Step 7 - Reviewing and undoing changes
DNF records every transaction and can undo it, which is one of its main advantages over APT:
sudo dnf history
ID | Command line | Date and time | Action(s) | Altered
------------------------------------------------------------------------------
12 | install nginx | 2026-09-25 09:40 | Install | 4
11 | upgrade | 2026-09-24 07:02 | Upgrade | 31
Show the details of one transaction and undo it:
sudo dnf history info 12
sudo dnf history undo 12
Undoing an upgrade only works while the older package versions are still available in the repositories.
APT has no rollback command, but it logs every run. Check what changed and when:
less /var/log/apt/history.log
To go back on Ubuntu, reinstall the previous version explicitly as shown in Step 3, which is why a disk snapshot before large upgrades is valuable.
Step 8 - Automating security updates
Ubuntu installs and enables unattended-upgrades by default, which applies security updates daily. Verify that it is active:
systemctl status unattended-upgrades
cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Run a dry run to see what it would do:
sudo unattended-upgrade --dry-run --debug
On Rocky Linux, install dnf-automatic, set it to apply only security updates, and enable its timer:
sudo dnf install dnf-automatic
sudo nano /etc/dnf/automatic.conf
In the [commands] section, set:
[commands]
upgrade_type = security
apply_updates = yes
Enable the timer and check when it will run next:
sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timer
To apply only security updates manually, run sudo dnf upgrade --security.
Command equivalents
| Task | APT (Ubuntu, Debian) | DNF (Rocky, AlmaLinux) |
|---|---|---|
| Refresh metadata | sudo apt update | sudo dnf makecache |
| List updates | apt list --upgradable | dnf check-update |
| Upgrade everything | sudo apt full-upgrade | sudo dnf upgrade |
| Install | sudo apt install pkg | sudo dnf install pkg |
| Remove | sudo apt remove pkg / purge pkg | sudo dnf remove pkg |
| Remove unused dependencies | sudo apt autoremove | sudo dnf autoremove |
| Search | apt search term | dnf search term |
| Package details | apt show pkg | dnf info pkg |
| Which package owns a file | dpkg -S /path | rpm -qf /path |
| Files in a package | dpkg -L pkg | rpm -ql pkg |
| Hold a version | sudo apt-mark hold pkg | sudo dnf versionlock add pkg |
| Transaction history | /var/log/apt/history.log | dnf history |
| Clean the cache | sudo apt clean | sudo dnf clean all |
Troubleshooting
Could not get lock /var/lib/dpkg/lock-frontend. Another APT process is running, very often unattended-upgrades shortly after boot. Wait for it to finish and check what holds the lock with ps aux | grep -E 'apt|dpkg'. Do not delete the lock files: interrupting dpkg mid-install is how packages end up broken.
dpkg was interrupted, you must manually run 'sudo dpkg --configure -a'. A previous installation was cut off. Finish configuring the pending packages and let APT repair dependencies:
sudo dpkg --configure -a
sudo apt --fix-broken install
The following packages have unmet dependencies. Usually caused by a third-party repository or a manually installed .deb built for another release. Run sudo apt --fix-broken install, then check with apt-cache policy package_name which repository each version comes from.
NO_PUBKEY or The repository is not signed on apt update. The key in the Signed-By path is missing, wrong or expired. Download the current key from the vendor again as shown in Step 6.
DNF metadata or checksum errors. Clear the cached metadata and download it again:
sudo dnf clean all
sudo dnf makecache
DNF reports conflicting packages. Read the conflict message: it names the two packages and usually the repositories they come from. Remove or disable the repository that provides the incompatible version, or retry with --allowerasing after checking which packages DNF proposes to remove. Never force-install with rpm --nodeps.
Conclusion
You now know how to perform the everyday package tasks on both major Linux families: keeping the system updated, finding and installing software, pinning versions, adding signed third-party repositories, rolling back changes and fixing the most common errors. As next steps, make sure automatic security updates are active on every server, snapshot servers before large upgrades, and read the guide on upgrading Ubuntu LTS to a new version when your release approaches end of life.
