Alright, let’s pull back the curtain. You’ve been using apt this whole time, and it’s been wonderful—fetching packages, resolving dependencies, making you a cup of tea. But apt is a high-level concierge; it’s not the one schlepping the heavy boxes off the truck. That grunt work, the actual business of unpacking .deb files and putting the pieces in the right places on your filesystem, is handled by dpkg.

Think of dpkg as the foundation of the whole Debian/Ubuntu package management empire. apt calls dpkg. dpkg does the dirty work. It’s a powerful, no-nonsense tool that operates on individual .deb files. You use it directly when you’ve downloaded a package by hand, when you need to introspect what’s installed, or when something has gone horribly wrong and you need to perform surgery.

The Anatomy of a .deb File

First, it’s not magic. A .deb file is just an ar archive (a old-school format for bundling files, like .tar but older). You can crack one open with any archiving tool, but let’s do it the proper way. Inside, you’ll find three files (usually):

  1. debian-binary: Just a text file stating the version number of the deb format. Spoiler: it’s usually 2.0.
  2. control.tar.gz: This is the metadata—the package’s name, version, description, and crucially, its dependencies (Depends), what it conflicts with (Conflicts), and what it provides (Provides).
  3. data.tar.gz (or data.tar.xz etc.): This is the actual payload—the executable binaries, config files, and documentation that get extracted onto your root filesystem (/).

You can play along at home. Let’s say you have vim_*.deb downloaded. You can list its contents without installing it:

dpkg --contents vim_*.deb

Or, to see the juicy control information:

dpkg --info vim_*.deb

This is your first line of defense. Before installing some random .deb from the internet, always --info it. See what it Depends on. If your system doesn’t have those dependencies, the installation will fail, and you’ll be in dependency hell. Which, by the way, is a real place, and it has a sign that says “Abandon all hope, ye who enter here.”

Installing a Package Directly (and the Dependency Problem)

Installing a local .deb file is straightforward, until it very much isn’t.

sudo dpkg -i /path/to/your/cool-package.deb

The -i flag means “install.” dpkg will unpack the data archive, put files in /usr/bin, /etc, and wherever else, and run any pre- and post-installation scripts. Then it will promptly tell you it has errors because cool-package depends on libsome-obscure-thing version 3.14 and you have version 2.71.

This is dpkg’s core limitation: it does not handle dependencies. It will happily try to install the package, but if dependencies aren’t met, it will mark the package as “unpacked” but not “configured.” It’s in a half-broken state.

This is where you get to play the hero. You can run:

sudo apt-get install -f

The -f stands for “–fix-broken.” This command tells apt to look at the mess dpkg just made (or that you’ve gotten yourself into), figure out what dependencies are missing, grab them from the repository, and install them to satisfy the broken package. It’s the one-two punch: dpkg -i to get the package on the system, then apt-get install -f to clean up the aftermath.

Interrogating the Database

dpkg maintains a database of every package installed on your system in /var/lib/dpkg. This is its crown jewel. You can query this database to see what’s what.

To list every single installed package on your system (it’s a long list):

dpkg -l

To check if a specific package is installed and get its version:

dpkg -l package-name

To find out which package owns a file you’re looking at (a lifesaver):

dpkg -S /usr/bin/apt

And the reverse: list all the files that were installed by a package:

dpkg -L package-name

This last one is incredibly useful for debugging. If a program is acting weird, you can see exactly what files it dropped on your system, especially in /etc where its configuration lives.

The Nuclear Option: Purging

Removing a package is done with -r (remove) or -P (purge). This is a critical distinction.

sudo dpkg -r package-name

This removes the installed files but leaves the configuration files behind on your system. It’s the “I might reinstall this later” option.

sudo dpkg -P package-name

This is the “I never want to see a trace of this thing again” option. It removes the package and deletes all of its configuration files from your system. Use this when you want a truly clean slate. Be warned: if that config file was in /etc and you’ve edited it, purge will nuke your customizations without a second thought. It’s ruthless, and I respect that.

So, when do you use dpkg directly? When you’re handed a .deb file on a USB stick like it’s 1999. When you need to inspect exactly what a package contains. When apt is having a meltdown and you need to manually force-install or remove a package to untangle the knot. It’s your surgical tool. Use it wisely, and always have apt-get install -f loaded in the chamber ready to clean up your mess.