Linux Administration Lesson 13 – Package Management | Dataplexa
Section II — User, Process & Package Management

Package Management

In this lesson

apt and dpkg dnf and rpm Repositories Querying packages Holding and pinning

Package management is the system Linux uses to install, update, configure, and remove software in a controlled and repeatable way. Instead of downloading executables from websites, a package manager retrieves verified, pre-built software bundles from trusted repositories, resolves all dependencies automatically, and maintains a complete record of what is installed — making the entire software lifecycle auditable and reversible.

The Package Management Landscape

Linux package management splits into two major ecosystems based on distribution family. Debian-based systems (Ubuntu, Debian, Linux Mint) use .deb packages managed by apt and dpkg. Red Hat-based systems (RHEL, Rocky Linux, Fedora, AlmaLinux) use .rpm packages managed by dnf and rpm. Understanding both is essential for any professional Linux administrator.

Linux Package Management Ecosystems Debian / Ubuntu Family Ubuntu Debian Linux Mint apt high-level tool dpkg low-level tool .deb package format Red Hat Family RHEL Rocky Fedora / Alma dnf high-level tool rpm low-level tool .rpm package format High-level tools handle dependency resolution · Low-level tools operate directly on package files

Fig 1 — The two major Linux package ecosystems and their toolchains

Analogy: Think of apt and dnf as the app store on your phone — they find what you want, download it, and handle everything the app needs to work. dpkg and rpm are the installer underneath — they do the actual file placement, but won't go fetch missing dependencies for you.

apt — Package Management on Debian and Ubuntu

apt (Advanced Package Tool) is the primary interface for managing software on Debian-family systems. It works by fetching package metadata from repositories listed in /etc/apt/sources.list and /etc/apt/sources.list.d/, then resolving and installing dependencies automatically.

apt — Essential Commands
Command What it does
apt update Refresh the local package index from all configured repositories. Does not install anything.
apt upgrade Upgrade all installed packages to their latest available versions without removing any packages.
apt full-upgrade Upgrade packages, and also remove or install packages as needed to satisfy dependencies. More aggressive than upgrade.
apt install <pkg> Install a package and all its dependencies.
apt remove <pkg> Remove a package but keep its configuration files on disk.
apt purge <pkg> Remove a package and delete all its configuration files.
apt autoremove Remove packages that were installed as dependencies but are no longer needed by anything.
apt search <term> Search the package index for packages matching a name or description.
apt show <pkg> Display detailed information about a package — version, size, dependencies, description.
# The standard update-then-upgrade sequence — run this regularly
sudo apt update && sudo apt upgrade -y

# Install a package
sudo apt install nginx -y

# Install multiple packages at once
sudo apt install curl wget git vim -y

# Remove a package, keeping config files (useful if you plan to reinstall)
sudo apt remove nginx

# Purge a package and all its config files — clean removal
sudo apt purge nginx

# Remove orphaned dependency packages after a removal
sudo apt autoremove -y

# Search for packages by name or description
apt search "web server"

# Show full package details before installing
apt show nginx

# List all installed packages
dpkg --list
apt list --installed

What just happened? apt show retrieved nginx's full metadata from the local package index — including its exact version, download size, dependency chain, and the repository it will be fetched from. This is the correct way to preview a package before installing it on a production system.

dnf and rpm — Package Management on RHEL and Rocky

dnf (Dandified YUM) is the modern package manager for Red Hat-based systems, replacing the older yum. Its command structure is intentionally similar to apt, making it straightforward to switch between distributions once you know either one.

apt (Debian / Ubuntu)

apt update
apt upgrade -y
apt install nginx
apt remove nginx
apt purge nginx
apt search nginx
apt show nginx
apt autoremove

dnf (RHEL / Rocky / Fedora)

dnf check-update
dnf upgrade -y
dnf install nginx
dnf remove nginx
dnf remove nginx + autoremove
dnf search nginx
dnf info nginx
dnf autoremove
# Update package index and upgrade all packages (RHEL/Rocky)
sudo dnf check-update
sudo dnf upgrade -y

# Install a package
sudo dnf install nginx -y

# Install a package group (e.g. development tools)
sudo dnf groupinstall "Development Tools" -y

# Remove a package
sudo dnf remove nginx -y

# Search for a package
dnf search "web server"

# Show detailed package info
dnf info nginx

# List all installed packages
dnf list installed

# View transaction history — every install/remove/upgrade ever run
dnf history

# Undo the last transaction (rollback)
sudo dnf history undo last

What just happened? dnf history showed a complete audit trail of every package operation on the system. This is a key operational advantage of dnf over apt — individual transactions can be reviewed and rolled back, making it possible to undo a bad upgrade without a full system restore.

Working with Repositories

A repository is a structured collection of packages hosted on a server that your package manager is configured to trust. Managing repositories — adding third-party sources, enabling or disabling them, and verifying their GPG keys — is a routine part of Linux administration.

Step 1 — Import the repository's GPG signing key

The GPG key allows your package manager to verify that packages from this repository have not been tampered with. Never add a repository without importing its key first.

# Debian/Ubuntu curl -fsSL https://repo.example.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg

Step 2 — Add the repository source entry

Add a source line pointing to the repository URL, referencing the key you just imported.

# Debian/Ubuntu — write to a dedicated file in sources.list.d/ echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://repo.example.com stable main" | \ sudo tee /etc/apt/sources.list.d/example.list

Step 3 — Update the package index

Refresh the local index so the new repository's packages are visible to the package manager.

sudo apt update # Debian/Ubuntu sudo dnf check-update # RHEL/Rocky

Step 4 — Install from the new repository

The package is now available just like any other. You can optionally pin to a specific version from this repo.

sudo apt install example-package -y
# List all currently configured repositories (Debian/Ubuntu)
cat /etc/apt/sources.list
ls /etc/apt/sources.list.d/

# List all enabled repositories (RHEL/Rocky)
dnf repolist
dnf repolist all     # includes disabled repos

# Enable or disable a repo (RHEL/Rocky)
sudo dnf config-manager --enable epel
sudo dnf config-manager --disable epel

# Add the EPEL repository on RHEL/Rocky (common source for extra packages)
sudo dnf install epel-release -y

# Remove a third-party apt repository
sudo rm /etc/apt/sources.list.d/example.list
sudo apt update

What just happened? The Docker repository is a perfect real-world example of the correct pattern — its entry in sources.list.d/ explicitly references its own GPG key file via signed-by=, meaning packages from that repo can only be installed if they are signed by Docker's key. This is the modern, secure way to add third-party repositories.

Querying and Inspecting Packages with dpkg and rpm

While apt and dnf are used for installing and removing packages, the low-level tools dpkg and rpm are invaluable for querying exactly what is installed, which package owns a specific file, and what files a package contains.

dpkg -l
List all installed packages

Shows every package currently installed on the system with its version and status. Pipe through grep to search: dpkg -l | grep nginx

dpkg -L <pkg>
List all files installed by a package

Essential for finding where a package put its config files, binaries, and man pages: dpkg -L nginx

dpkg -S <file>
Find which package owns a file

Given any file path, returns the package that installed it: dpkg -S /usr/bin/curl. Extremely useful when troubleshooting.

rpm -qa
Query all installed RPM packages

Lists every installed package with version and release: rpm -qa | grep nginx

rpm -ql <pkg>
List all files in an RPM package

Same as dpkg -L but for RPM packages: rpm -ql nginx

rpm -qf <file>
Find which RPM package owns a file

Same as dpkg -S for RPM systems: rpm -qf /usr/bin/curl

# Find which package owns the curl binary (Debian/Ubuntu)
dpkg -S /usr/bin/curl

# Find which package owns a file (RHEL/Rocky)
rpm -qf /usr/bin/curl

# List every file installed by the nginx package (Debian/Ubuntu)
dpkg -L nginx

# List every file installed by the nginx package (RHEL/Rocky)
rpm -ql nginx

# Check if a specific package is installed (Debian/Ubuntu)
dpkg -l nginx | grep ^ii

# Check if a specific package is installed (RHEL/Rocky)
rpm -q nginx

What just happened? dpkg -S and rpm -qf are invaluable during incident investigation — if a binary has been replaced or tampered with, these commands tell you which package originally installed it, so you can reinstall the package to restore the legitimate file.

Holding Packages and Version Pinning

In production environments, automatically upgrading every package on every apt upgrade can break applications that depend on a specific version. Holding (Debian) and version locking (RHEL) prevent a package from being upgraded until you explicitly release the hold.

# Hold a package at its current version (Debian/Ubuntu)
sudo apt-mark hold nginx

# Verify which packages are held
apt-mark showhold

# Release a hold to allow upgrades again
sudo apt-mark unhold nginx

# Install a specific version of a package (Debian/Ubuntu)
sudo apt install nginx=1.24.0-2ubuntu7

# Lock a package to its current version (RHEL/Rocky — requires versionlock plugin)
sudo dnf install dnf-plugin-versionlock -y
sudo dnf versionlock add nginx

# List all locked packages
sudo dnf versionlock list

# Remove a version lock
sudo dnf versionlock delete nginx

What just happened? With the hold in place, apt upgrade ran successfully but silently skipped nginx and postgresql — reporting them as "kept back" rather than failing. This is the correct production pattern: run automated security updates across the whole system, while manually controlling upgrades for business-critical packages.

Never Run apt upgrade Without apt update First

Running apt upgrade without first running apt update upgrades packages against a stale index — you may install an outdated version of a package that has since received a critical security patch. Always run sudo apt update && sudo apt upgrade -y as a single chained command. Similarly, never pipe the install flag (-y) blindly on production systems without reviewing what will change — reserve -y for automated scripts where the scope is already controlled.

Lesson Checklist

I understand the difference between high-level tools (apt, dnf) and low-level tools (dpkg, rpm), and know when to use each
I always run apt update before apt upgrade, and I know the equivalent dnf commands for RHEL-family systems
I can add a third-party repository safely by importing its GPG key first and adding it to a dedicated file in sources.list.d/
I can use dpkg -S / rpm -qf to find which package owns any file, and dpkg -L / rpm -ql to list all files a package installed
I can hold or pin a package at a specific version using apt-mark hold or dnf versionlock to prevent uncontrolled upgrades on production systems

Teacher's Note

The dpkg -S and rpm -qf commands are used far less often than they should be. Whenever a binary behaves unexpectedly or you need to know where a config file came from, these commands answer the question in one second — make them part of your standard troubleshooting reflex.

Practice Questions

1. On a Debian/Ubuntu server, you need to install PostgreSQL 15, then ensure it is never accidentally upgraded during a routine apt upgrade. Write every command required, and explain how you would verify the hold is in place.

2. A colleague reports that the binary at /usr/bin/ssh may have been replaced on a Rocky Linux server. Describe how you would use low-level RPM tools to identify which package owns that file and then reinstall the package to restore it to its original state.

3. Explain the difference between apt remove and apt purge. In what scenario would you prefer remove over purge, and when would purge be the correct choice?

Lesson Quiz

1. What is the key difference between apt upgrade and apt full-upgrade?

2. You run dpkg -S /etc/nginx/nginx.conf and get no output. What does this most likely indicate?

3. Why is it important to import a repository's GPG key before adding it to your package manager's source list?

Up Next

Lesson 14 — System Services and systemd

Managing, enabling, and troubleshooting system services using systemctl and journalctl