Mastering DEB Package Installation on Ubuntu: Beyond the Basics
Enterprise environments often mandate installing internal applications or vendor tools distributed as raw .deb
files. Relying solely on apt
or Snap won’t cover these cases. Understanding .deb
installations—mechanics, caveats, and troubleshooting—avoids system drift and broken dependency chains, especially on Ubuntu (20.04 LTS, 22.04 LTS).
DEB Format Overview
A .deb
package is essentially a ar
archive with two main tarballs: control.tar.*
(metadata, scripts, dependencies) and data.tar.*
(payload). Package installation involves unpacking, dependency management, and firing off pre/post install scripts. Running apt install some-package
is just an automated way of manipulating .deb
files under /var/cache/apt/archives/
.
Direct Installation Using dpkg
Deploying a .deb
with dpkg -i
offers granular control. Example:
sudo dpkg -i gitlab-runner_16.3.2_amd64.deb
Relevant output on missing dependencies (inevitable with “fat” packages):
dpkg: dependency problems prevent configuration of gitlab-runner:
gitlab-runner depends on libc6 (>= 2.31); however:
Package libc6 is not installed.
Note: dpkg
does not pull missing dependencies. After initial failure, immediately follow with:
sudo apt-get install -f
This backfills any unsatisfied libraries or runtime packages. Failure to fix leaves the new package in an “unconfigured” state; see dpkg -l | grep ^..i
for partial installs.
Installing with apt
(Dependency Resolution Included)
Modern Ubuntu (apt >= 1.1
, i.e., since 16.04) accepts local .deb
files and solves dependencies inline:
sudo apt install ./gitlab-runner_16.3.2_amd64.deb
- The
./
prefix is critical; without it,apt
searches repositories only. - This approach is preferable for daily admin use, except when scripting base images or chroot environments, where repo access might not be possible.
Previewing and Auditing Packages
Blindly installing vendor .deb
files risks overwriting critical binaries or polluting /usr/local/bin
. Always review package contents:
dpkg-deb -c gitlab-runner_16.3.2_amd64.deb
Sample output (truncated):
drwxr-xr-x root/root 0 2023-09-10 15:28 ./
drwxr-xr-x root/root 0 2023-09-10 15:28 usr/
drwxr-xr-x root/root 0 2023-09-10 15:28 usr/bin/
-rwxr-xr-x root/root 5198460 2023-09-10 15:28 usr/bin/gitlab-runner
Check package metadata and dependencies before install:
dpkg-deb -I gitlab-runner_16.3.2_amd64.deb
Look for fields like Depends
, Conflicts
, and Pre-Depends
. If you spot a Conflicts
or a tight version Depends:
, expect potential breakage.
Removing a Manual .deb
Install
Standard removal (whether you used dpkg
or apt
):
sudo apt remove gitlab-runner
or, lower-level:
sudo dpkg -r gitlab-runner
Gotcha: Removing via dpkg -r
does not remove dependencies you installed for this package; consider cleaning up with:
sudo apt autoremove
after uninstalling.
Typical Failure Scenarios & Remediation
1. Unmet Dependencies
- Seen as:
dpkg: error processing package gitlab-runner (--install): dependency problems - leaving unconfigured
- Solution:
sudo apt-get install -f
2. Broken Packages
- Actions:
sudo dpkg --configure -a
3. Outdated or Broken APT Cache
- Clear and refresh:
sudo apt-get clean sudo apt-get update
4. Package Version Conflict
- Investigate:
sudo apt-cache policy conflicting-package sudo apt-get remove conflicting-package
5. Leftover: Partially installed .deb
leaves the system “dirty” (not uncommon in CI images).
Always verify state with:
dpkg -l | grep ^..i
Automating .deb
Installs (Scripted Provisioning)
In CI/CD pipelines or during fleet provisioning, chain dpkg
with dependency remediation:
#!/usr/bin/env bash
set -e
sudo dpkg -i ./app-special_2.1.6_amd64.deb || sudo apt-get install -f -y
Note: This pattern is brittle if apt-get install -f
must pull from non-default sources (e.g., private repositories). Mirror those repositories, or pre-stage all dependency .deb
files.
Verifying Downloaded Package Integrity
“Trust but verify”—especially for manually downloaded .deb
from third parties.
sha256sum gitlab-runner_16.3.2_amd64.deb
Compare output against vendor documentation.
If a .deb
includes a signature file (*.deb.asc
), validate with gpg --verify
.
Side Notes & Non-Obvious Tips
- Many
.deb
packages execute maintainer scripts (postinst
,prerm
). Inspect withdpkg-deb -e
. - Installing a
.deb
withapt
will record the package as “manually installed”, affecting howapt autoremove
treats it. - For a quick dry-run to check conflicts without committing:
apt install --simulate ./foo.deb
- Some graphical tools (e.g., GDebi, Ubuntu Software Center) provide similar functionality but abstract key errors. Recommend CLI for unambiguous troubleshooting.
Bottom Line
Direct handling of .deb
packages on Ubuntu is both power and pitfall. Use dpkg
for root-level control, but rely on apt
for day-to-day operations to prevent orphaned dependencies. Always audit, verify, and log every manual package install—especially in production environments. Automate repeatable patterns, but expect and design for occasional breakage.
If a package won’t install cleanly with either dpkg
or apt
, stop and audit. Rushing may pollute your core system libraries or leave future upgrades broken.
For more nuanced automation, consider FPM or building your own APT repo—manual .deb
installs scale poorly past a few systems.
Reference environments for this guide: Ubuntu 20.04.6 LTS, 22.04.4 LTS, dpkg 1.19.7, apt 2.0.6.
For nuanced deployments or edge cases, don't hesitate to inspect upstream package source or maintain a local repository.