13.1 dpkg Fundamentals
Key Takeaways
- dpkg is the low-level Debian package tool: it installs and removes individual .deb files but performs no dependency resolution or repository downloads
- dpkg -i installs a local .deb file; dpkg -r removes a package but leaves its conffiles, while dpkg -P (purge) removes the package and its conffiles
- The first two columns of dpkg -l output encode desired state and current status: ii means installed, rc means removed with conffiles remaining, un means never installed
- dpkg --configure -a re-runs configuration for every unpacked-but-unconfigured package and is the standard recovery step after an interrupted install
- APT is a front-end layered on top of dpkg: apt fetches packages from repositories and resolves dependencies, then hands the actual installation work to dpkg
What dpkg Actually Does
dpkg is the low-level package manager at the heart of every Debian-based system, including Kali Linux. Every package you install — whether you typed apt install nmap or dpkg -i something.deb — ultimately passes through dpkg, because dpkg is the tool that unpacks archives, runs maintainer scripts, and records package state in its database at /var/lib/dpkg/. APT (Advanced Package Tool) is a higher-level front-end layered on top of dpkg: it downloads packages from repositories like kali-rolling, resolves dependency chains, verifies signatures, and then invokes dpkg to perform the actual installation.
This division of labor is a favorite exam topic. The rule is simple: dpkg works only on files that already exist on your disk and knows nothing about dependencies or repositories. If a package needs libraries that are not installed, dpkg will fail and leave the package half-configured; apt would have fetched those libraries automatically.
Installing a Local Package: dpkg -i
Use dpkg -i (or the long form dpkg --install) to install a .deb file you have already downloaded:
$ sudo dpkg -i /home/kali/Downloads/mypackage_1.2.3_amd64.deb
Selecting previously unselected package mypackage.
(Reading database ... 312450 files and directories currently installed.)
Preparing to unpack .../mypackage_1.2.3_amd64.deb ...
Unpacking mypackage (1.2.3) ...
Setting up mypackage (1.2.3) ...
You can pass several .deb files in one command, or use dpkg -iR /path/to/dir/ (--recursive) to install every package found under a directory tree. The danger appears when dependencies are missing:
dpkg: dependency problems prevent configuration of mypackage:
mypackage depends on libfoo2 (>= 2.0); however:
Package libfoo2 is not installed.
dpkg still unpacks the package but leaves it unconfigured (an iU state). The classic fix is sudo apt -f install (--fix-broken), which asks apt to fetch the missing dependencies from the configured repositories and finish the job dpkg could not. Remember: dpkg itself will never go to the network to solve this for you.
Removing vs Purging: dpkg -r and dpkg -P
Two commands remove packages, and the difference matters on the exam:
dpkg -r package(--remove) deletes the package's files but keeps its conffiles — the configuration files under/etcthat dpkg tracks specially. This is deliberate: if you reinstall later, your settings are still there.dpkg -P package(--purge) removes the package including its conffiles, leaving no dpkg-tracked trace behind.
Note that even a purge does not touch files created at runtime — log files in /var/log, data in /var/lib, or per-user dotfiles in home directories are the administrator's problem, not dpkg's.
Reading dpkg -l and the Status Flags
dpkg -l lists every package dpkg knows about. Each line begins with a status code whose first two letters you must be able to decode:
| Code | First letter (desired state) | Second letter (current status) | Meaning |
|---|---|---|---|
ii | i = install | i = installed | Package is installed and configured — the normal state |
rc | r = remove | c = config-files | Removed, but conffiles remain on disk |
un | u = unknown | n = not-installed | Package was never installed |
iU | i = install | U = unpacked | Unpacked but not configured (interrupted or missing deps) |
iF | i = install | F = half-configured | Configuration failed partway through |
The first column is the desired state (what you asked for: u unknown, i install, r remove, p purge, h hold), the second is the current status (n not-installed, i installed, c config-files only, U unpacked, F half-configured, H half-installed, W triggers-awaited, t triggers-pending — dpkg prints the "bad" states in uppercase), and a possible third column flags an error (R means reinstallation required). A classic trap: rc does not mean "running config" or "recently changed" — it means the package was removed and only its configuration files survive. You can filter on this directly, for example dpkg -l | grep '^rc' to find leftover conffiles you might want to purge.
dpkg --get-selections is a related query: it prints just the package name and desired state (install, deinstall, purge, hold), and piping it back into dpkg --set-selections is how administrators clone a package set onto another machine.
Recovering from an Interrupted Install
If an install is cut short — a Ctrl-C at the wrong moment, a dead SSH session, a power failure — packages can be left unpacked but unconfigured. The recovery command is:
$ sudo dpkg --configure -a
The -a (or --pending) flag tells dpkg to configure every package that is unpacked but not yet configured. You will also see apt suggest this exact command when its own operations detect a broken state. Do not confuse this with dpkg-reconfigure package, which is a debconf helper that re-asks a package's configuration questions — a different tool for a different problem.
dpkg vs apt: Scope and Responsibility
| Capability | dpkg | apt |
|---|---|---|
Install local .deb files | Yes | Yes (apt install ./file.deb) |
| Download from repositories | No | Yes |
| Dependency resolution | No (reports problems only) | Yes, automatic |
| Signature/repository verification | No | Yes |
| Unpacks files, runs maintainer scripts | Yes | Delegates to dpkg |
| Tracks the package database | Yes (/var/lib/dpkg) | Uses dpkg's database |
The mental model to carry into the exam: apt decides what to install and fetches it; dpkg physically installs it. When a question asks which tool "cannot resolve dependencies" or "operates only on local .deb files," the answer is dpkg. When a question asks which tool talks to kali-rolling, the answer is apt.
Two final operational flags round out the fundamentals. To stop apt from upgrading a package, put it on hold: echo "nmap hold" | sudo dpkg --set-selections (or sudo apt-mark hold nmap) flips its desired state to h, and dpkg -l then shows hi. And dpkg --audit (-C) lists packages that are only partly installed or otherwise need attention — a quick health check of the dpkg database before a big upgrade.
You run dpkg -l | grep apache2 and see the line rc apache2 2.4.62-1 amd64 Apache HTTP Server. What does the rc status tell you about the system?
A package upgrade on a headless Kali server is cut short when the SSH session drops mid-install. After reconnecting, dpkg -l shows several packages in the iU state — unpacked but not configured. Which command finishes configuring them?