Alright, let’s get our hands dirty with rpm. Forget the fancy, high-level package managers for a second. This is the foundation. rpm is the grumpy, meticulous, and brutally efficient librarian who handles the actual books (packages) on the shelves. yum and dnf are the friendly librarians who talk to you, figure out what you need, and then go bother the grumpy one to actually do the work. To really understand what’s going on, you need to talk directly to the grump.

The Anatomy of an RPM File

First, what are you even dealing with? An .rpm file isn’t just a tarball with a fancy extension. It’s a deeply structured archive with four sections. Think of it like a shipping container for software:

  1. The lead: A quaint, ancient header for identifying the file. We can mostly ignore this.
  2. The signature: This is the tamper-proof seal. It’s a cryptographic signature (often GPG) that allows rpm to verify the package came from your distro and hasn’t been messed with. You’ll see why this matters in a bit.
  3. The header: This is the manifest. It contains all the metadata about the package in a structured, easily queryable format: the name, version, description, list of files, checksums of those files, and crucially, information about dependencies (requires) and what this package provides (provides).
  4. The payload: The actual goods! This is a cpio archive (usually compressed with xz or zstd) containing all the files to be installed on your system.

You can poke at this structure with rpm itself. The -qip flags are your friend here. Let’s say you’ve downloaded some-cool-app.rpm and want to see what’s inside before you install it.

# Query Info about a Package file (that's the -qi p)
rpm -qip some-cool-app.rpm

This will spit out all the header metadata: Name, Version, Release, Architecture, Group, License, the URL for the source code, the packager’s name, a summary, and a full description. It’s your first line of defense against installing something silly.

Installing and (More Importantly) Uninstalling

Installing a single, local .rpm file is straightforward. But here’s the first “questionable choice” you’ll encounter. The flag for install is -i (for install), but no one in their right mind uses it by itself. Why? Because it’s utterly deaf to the screams of your system’s dependency needs. You always use -v (verbose) and -h (print hash marks as a progress bar) with it. So the incantation is:

# The correct way to install a local RPM. The -U for "Upgrade" is also common.
rpm -ivh some-cool-app.rpm

If some-cool-app.rpm needs libsomething.so.5, but you only have libsomething.so.4, the install will fail spectacularly. This is rpm’s core design philosophy: it will never break its internal database’s consistency. It would rather fail and let you figure it out than leave you with a half-broken system. You have to respect that, even if it’s infuriating.

Now, uninstalling. This uses the -e (for erase) flag. Crucial pitfall alert: You don’t specify the .rpm file name here. You specify the package name as it’s known in the RPM database.

# Wrong! This will likely fail.
rpm -evh some-cool-app.rpm

# Correct! Uninstall by the package name.
rpm -evh some-cool-app

If you get this wrong, rpm will look for a package literally named “some-cool-app.rpm” in its database, won’t find it, and will do nothing. It’s a classic “I’m a computer, I do exactly what you say” moment.

Querying All the Things

This is where rpm shines. Its database (/var/lib/rpm) is a rich, local source of truth about every single file installed by a package. The query command is -q, and it’s immensely powerful. You’ll live and die by these commands.

Want to know if a package is installed, and what its version is?

rpm -q bash

Want to know which package owns a specific file? This is magic when you get a “file not found” error but you’re sure it should be there.

rpm -qf /usr/bin/vim

Want to list all the files that were installed by a package? Incredibly useful for debugging, confirming config file locations, or seeing where the heck that binary went.

rpm -ql httpd

The database also tracks checksums and file metadata. Want to see the state of all the files from a package? This shows the mode, owner, group, size, and checksum for each file.

rpm -q --dump httpd

Verifying Package Integrity

Remember that signature and the checksums in the header? This is where we use them. The -V (or --verify) command is your system’s health check. It goes through all the files in a package and compares their current state on disk against the information recorded in the RPM database.

It checks nine different attributes, and if something is wrong, it outputs a string of characters telling you what’s different.

# Verify the 'bash' package
rpm -V bash

If you get no output, congratulations, nothing is wrong. If you get output, it looks like this:

S.5....T.  /bin/bash

This hieroglyphic means:

  • S : File Size differs
  • 5 : MD5 checksum differs (the big one!)
  • T : Modification Time differs

A changed config file (which you edited) is usually fine and expected. A changed binary is a massive red flag. This is your first command to run if you think your system has been compromised or a disk error has corrupted a file.

The Big Limitation and Best Practice

Here’s the brutal honesty: using rpm by itself to install things from the internet is a recipe for “dependency hell.” You’ll try to install A, which needs B, so you find B, which needs C, and C needs a newer version of A. It’s a fractal nightmare.

Best practice: Use rpm directly for querying and verifying packages already on your system. It’s the ultimate diagnostic tool. For installing local packages, use dnf localinstall ./package.rpm (or yum localinstall on older systems). This allows the higher-level tool to resolve dependencies from your enabled repositories, saving you from the aforementioned hell. Use raw rpm -i only when you absolutely know what you’re doing and have all the dependencies already satisfied. Consider it a power tool, not your everyday hammer.