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 sudo privileges.

How APT, YUM and DNF relate

Debian, UbuntuRHEL, 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)dpkgrpm
Repository configuration/etc/apt/sources.list.d//etc/yum.repos.d/
Automatic updatesunattended-upgradesdnf-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

TaskAPT (Ubuntu, Debian)DNF (Rocky, AlmaLinux)
Refresh metadatasudo apt updatesudo dnf makecache
List updatesapt list --upgradablednf check-update
Upgrade everythingsudo apt full-upgradesudo dnf upgrade
Installsudo apt install pkgsudo dnf install pkg
Removesudo apt remove pkg / purge pkgsudo dnf remove pkg
Remove unused dependenciessudo apt autoremovesudo dnf autoremove
Searchapt search termdnf search term
Package detailsapt show pkgdnf info pkg
Which package owns a filedpkg -S /pathrpm -qf /path
Files in a packagedpkg -L pkgrpm -ql pkg
Hold a versionsudo apt-mark hold pkgsudo dnf versionlock add pkg
Transaction history/var/log/apt/history.logdnf history
Clean the cachesudo apt cleansudo 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.