Install a Local .deb with dpkg and Keep Your Bearings

You have a .deb file on disk and want it installed with dpkg without breaking anything on the way. You will inspect the package, preview the action, install it and confirm it is fully configured.

The examples match dpkg 1.22.6 on this machine, packaged as dpkg 1.22.6ubuntu6.6. Allow about fifteen minutes for a small package, plus time to investigate any dependency or configuration error.

Tip: This guide installs one package file. It does not choose dependencies or download anything. For a repository package with dependencies, use APT after checking its proposed changes.

1. Confirm the dpkg version and the package path

Check the executable and version before relying on an option. Keep the placeholder as a shell variable so it is harder to paste a different file into a privileged command by accident:

$ command -v dpkg
/usr/bin/dpkg
$ dpkg --version | head -1
Debian 'dpkg' package management program version 1.22.6 (amd64)
$ DEB_FILE='/path/to/package_1.2.3_amd64.deb'
$ test -r "$DEB_FILE" && echo "readable: $DEB_FILE"
readable: /path/to/package_1.2.3_amd64.deb

If the last command prints nothing, correct the path before continuing.

Warning: Do not use a filename from an untrusted source without checking where it came from and how it was authenticated. A successful dpkg operation is not proof that a package is trustworthy.

2. Inspect the archive without installing it

Use dpkg's front-end to dpkg-deb for metadata. This is read-only and should not need sudo:

$ dpkg --info "$DEB_FILE" | sed -n '1,24p'
 new Debian package, version 2.0.
 size ... bytes: control archive=...
 Package: example-package
 Version: 1.2.3
 Architecture: amd64
 Description: ...
$ dpkg --contents "$DEB_FILE" | sed -n '1,12p'

The exact size, description and file list depend on the archive. Check the package name, version and architecture before you give the file elevated access. --contents lists paths in the archive; it does not unpack them.

For a package that is already installed, compare the database record without changing anything:

$ dpkg-query --showformat='${Package} ${Version} ${Architecture}\n' --show example-package
example-package 1.2.3 amd64

Replace example-package with the name shown by --info. A missing package produces an error, which is useful information rather than a reason to guess a name.

3. Simulate the unpack before writing state

Run the same action with --no-act before the real install. Put the simulation option before the action. dpkg documents that placing it after the action can make it look like a package argument instead of a no-op request:

$ sudo dpkg --no-act --install "$DEB_FILE"
Selecting previously unselected package example-package.
(Reading database ...)
Preparing to unpack ...
Unpacking example-package (1.2.3) ...

Output varies with the package and with whether it is already installed. The command may mention dependency problems even though it writes nothing. Treat simulation as a preview, not a dependency solver. It cannot replace checking the package's declared dependencies or the change plan from your normal APT workflow.

Safety warning: Do not add --force-* to make a worrying preview disappear. dpkg warns that force options can break the system. Forcing conflicts, dependency checks, architecture checks or removal of essential or protected packages can leave a machine unbootable.

4. Install and watch the package stages

When the archive and preview look acceptable, install it. This changes state and normally needs elevated privileges:

$ sudo dpkg --install "$DEB_FILE"
Selecting previously unselected package example-package.
(Reading database ...)
Preparing to unpack ...
Unpacking example-package (1.2.3) ...
Setting up example-package (1.2.3) ...

For an upgrade, the order is:

  1. Old prerm runs.
  2. New preinst runs, and the files are unpacked.
  3. Old postrm runs.
  4. New postinst runs during configuration.

Warning: These maintainer scripts are executable code that runs as root. Review the package source and provenance before installing.

A maintainer script receives an action such as install, upgrade, configure, remove or purge, with version and replacement-package arguments in some cases. Do not invoke a script from /var/lib/dpkg/info manually to repair a failed operation. dpkg needs to maintain ordering, database state and rollback files.

5. Verify the resulting state

First query the package state. The final state you want is ii in the short listing and installed in dpkg's package state:

$ dpkg-query --show --showformat='${db:Status-Abbrev} ${Package} ${Version}\n' example-package
ii  example-package 1.2.3
$ dpkg --audit

A blank dpkg --audit result means no audit finding was printed. If the package is unpacked but not configured, or another package is half-installed, the audit output points to the affected area.

After a successful installation, you can also run:

$ sudo dpkg --verify example-package
$ dpkg-query -W -f='${Status}\n' example-package
install ok installed

The verify command normally prints only paths that fail a check. Missing metadata, inaccessible files and package-specific behaviour can change what it reports, so read it alongside the package status.

Tip: A clean dpkg --verify is not authenticity. It is an integrity check against recorded metadata, not a security verification.

Checkpoint: dpkg-query prints install ok installed and dpkg --audit prints nothing.

6. Recover from an incomplete configuration

If installation stops after unpacking, do not repeatedly force the same archive. Read the error, check the status, then ask dpkg to configure all unpacked packages that are pending:

$ dpkg-query --show --showformat='${db:Status-Abbrev} ${Package}\n' example-package
iU  example-package
$ sudo dpkg --configure --pending
Setting up example-package (1.2.3) ...

The exact status abbreviation can vary. --configure --pending runs pending configuration and trigger processing. If dependency packages are missing, use your normal APT frontend to resolve them, then repeat the pending configuration check. If a trigger was deliberately deferred with --no-triggers, the same command is the documented way to finish the pending trigger work.

Removing or purging is destructive. Removal keeps conffiles and some package-managed data. Purge also removes conffiles, and a package's postrm may remove additional system-directory data. Before either action, record the package name and back up configuration you need:

$ sudo cp --preserve=mode,ownership,timestamps /etc/example-package.conf /etc/example-package.conf.backup
$ sudo dpkg --remove example-package
# Undo the removal only by reinstalling the same package archive:
$ sudo dpkg --install "$DEB_FILE"

Destructive action: Do not purge merely to retry an installation. It can erase configuration that a reinstall would otherwise preserve.

7. Know the defaults that change the result

dpkg reads default options from /etc/dpkg/dpkg.cfg, matching fragments in /etc/dpkg/dpkg.cfg.d/, and, when present, ~/.dpkg.cfg. Each non-comment line is an option without its leading hyphens, and quoted values have their surrounding quotes stripped. Inspect these files when a command behaves differently from a clean shell:

$ sed -n '1,120p' /etc/dpkg/dpkg.cfg
$ find /etc/dpkg/dpkg.cfg.d -maxdepth 1 -type f -print -exec sed -n '1,80p' '{}' \;

A configuration file can enable logging, suppress signature verification attempts or add other defaults. Command-line options and environment such as DPKG_ADMINDIR can also redirect which database is used.

Warning: Confirm the target before using --root or --admindir, especially in automation.

Done means