Like most Linux package management, this is a two-layer system: a low-level tool that installs a single package file, and a higher-level tool that knows how to find packages, resolve dependencies between them, and fetch them from a repository.

dpkg: the low-level tool

dpkg installs, removes, and queries .deb package files directly, with no awareness of remote repositories and no automatic dependency resolution - if a .deb needs another package that isn't installed, dpkg will complain rather than fetch it for you.

sudo dpkg -i package.deb     # install a local .deb file
dpkg -l                       # list all installed packages
dpkg -L nginx                 # list every file nginx's package installed
dpkg -S /usr/bin/nginx        # which package owns this file?

dpkg -L and dpkg -S are especially useful for figuring out where a config file actually came from, or what else might break if you remove something.

APT: the layer you actually use day to day

APT (Advanced Package Tool) wraps dpkg, adding dependency resolution and repository management. apt is the modern, user-facing command; apt-get/apt-cache are the older, more scriptable commands it's gradually superseding for interactive use - both still work, and you'll see both in older documentation.

sudo apt update              # refresh the local package index from repositories
sudo apt upgrade             # upgrade all installed packages to latest available
sudo apt install nginx       # install a package, resolving dependencies automatically
sudo apt remove nginx        # remove the package, keep its config files
sudo apt purge nginx         # remove the package AND its config files
sudo apt autoremove          # remove packages that were installed as dependencies and are no longer needed
apt search "web server"      # search package names and descriptions
apt show nginx               # details about a specific package before installing

apt update doesn't install anything - it only refreshes APT's local knowledge of what's available. Forgetting to run it before install means you might get an outdated version, or a version that's already been pulled from the repository entirely.

Where repositories are configured

/etc/apt/sources.list.d/*.sources   # deb822 format - the default on Ubuntu 24.04+ and Debian 13+
/etc/apt/sources.list               # older one-line format, still read if present
/etc/apt/sources.list.d/*.list

Each entry names a repository URL, distribution codename (Suites:), and components (main, universe, restricted on Ubuntu). The newer .sources files use a Key: value block per repository; the older .list format packs the same information onto one line. Both still work. A current Ubuntu system's own repositories live in /etc/apt/sources.list.d/ubuntu.sources, with sources.list left empty.

Adding a third-party repository means adding a file here plus its signing key, saved under /etc/apt/keyrings/ and referenced from that repository's entry with Signed-By: (or [signed-by=...] in the one-line format) so the key is trusted for that repository only. The old apt-key add approach trusted a key for every repository and is deprecated. Be selective about what you add either way, since every repository you trust can push arbitrary code to your system via a package update.

Holding a package at its current version

Occasionally an upgrade should be deliberately skipped (a known-broken release, a kernel version you're pinning for driver compatibility):

sudo apt-mark hold linux-image-generic
sudo apt-mark unhold linux-image-generic

Checking what's actually available

apt-cache policy nginx
nginx:
  Installed: 1.24.0-2ubuntu7
  Candidate: 1.24.0-2ubuntu7
  Version table:
 *** 1.24.0-2ubuntu7 500
        500 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages
        100 /var/lib/dpkg/status

Useful for confirming which repository a version is actually coming from when multiple sources provide the same package name.

See DNF and RPM and Pacman for the equivalent stack on Fedora/RHEL and Arch, Building From Source for what to do when a package isn't available through any of these at all, and Flatpak, Snap, and AppImage for the distro-agnostic alternative to all of them.