APT (Debian/Ubuntu)

APT (Advanced Package Tool) is the command-line package manager used by Debian, Ubuntu, and every distribution built on them (Linux Mint, Pop!_OS, Raspberry Pi OS, and more). Instead of hunting down installers on random websites, you tell APT what software you want, and it downloads a vetted .deb package from a trusted repository, pulls in everything that package needs to run, and installs it all in one transaction. This lesson covers everything from your first apt install to how APT resolves dependencies under the hood and how to avoid the mistakes that break systems.

Overview: How APT Works

Software on Debian-based systems is distributed as .deb files – archives that bundle compiled binaries, configuration files, and metadata such as the package’s name, version, and the other packages it depends on. The tool that actually unpacks a .deb file onto disk is called dpkg. dpkg is low-level: give it a single .deb file and it will install it, but it has no idea how to find that file on the internet or what to do if it needs five other packages first.

APT sits on top of dpkg and solves exactly that problem. It manages a list of repositories (servers hosting collections of packages), keeps a local index of every package available in those repositories, computes which packages satisfy a request’s dependencies, downloads the right .deb files, and hands them to dpkg in the correct order.

Repositories and the package index

Repositories are configured in /etc/apt/sources.list and any .list files under /etc/apt/sources.list.d/. Each line names a URL, a distribution codename (like jammy for Ubuntu 22.04), and one or more components (main, universe, restricted, multiverse on Ubuntu). Running sudo apt update downloads the current package index from every configured repository and caches it under /var/lib/apt/lists/. This step does not install or upgrade a single package – it only refreshes APT’s knowledge of what versions are currently available. If you skip it, APT may try to fetch a package version that a mirror no longer serves, and you will see errors like 404 Not Found.

Dependency resolution

Every .deb package declares relationships to other packages: Depends (must be installed), Recommends (installed by default but skippable), Suggests (optional), and Conflicts (cannot coexist). When you run apt install, APT builds a dependency graph across the entire package index, and computes the smallest set of additional packages that satisfies every constraint. This is why installing one package can pull in a dozen others – and why APT shows you a summary of everything it’s about to change before it touches your system.

apt vs apt-get vs apt-cache

apt is the modern, user-friendly command introduced in 2014 that merges functionality previously split across apt-get (install/remove/upgrade) and apt-cache (search/inspect). It adds a progress bar and color output and is what you should type interactively. The older apt-get and apt-cache commands still exist and are preferred inside scripts, because APT’s own documentation warns that apt‘s command-line interface and output format may change between versions – apt-get‘s output is stable and scriptable.

Why sudo

Installing, removing, or upgrading packages writes to system directories like /usr, /etc, and /var, all of which are owned by root. APT itself needs to acquire a lock file before it can safely write to its package database, and only root (or a user invoking sudo) can create that lock, which is why every mutating APT command in this lesson is prefixed with sudo.

Syntax

The general form of an APT command is:

apt COMMAND [options] [package...]
Command What it does
update Refreshes the local package index from configured repositories (no installs/upgrades)
upgrade Installs newer versions of already-installed packages; never removes a package or installs a new one
full-upgrade Like upgrade, but will add or remove packages if needed to complete an upgrade
install <pkg> Installs a package and its dependencies
remove <pkg> Uninstalls a package’s programs but keeps its configuration files
purge <pkg> Uninstalls a package and deletes its configuration files too
autoremove Removes packages that were installed as dependencies and are no longer needed
search <term> Searches package names and descriptions in the local index
show <pkg> Prints detailed metadata for a package (version, dependencies, size, description)
list --installed Lists every package currently installed
list --upgradable Lists installed packages that have a newer version available

On RHEL, Fedora, and other Red Hat-family distributions, the equivalent tool is dnf (or the older yum) – the commands differ (dnf install, dnf remove, dnf search), but the concept of a repository-backed, dependency-resolving package manager is the same.

Examples

Example 1: Refresh the index and check what can be upgraded

sudo apt update
apt list --upgradable

Output:

Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [128 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Fetched 238 kB in 1s (238 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
5 packages can be upgraded. Run 'apt list --upgradable' to see them.

Listing...
curl/jammy-updates 7.81.0-1ubuntu1.15 amd64 [upgradable from: 7.81.0-1ubuntu1.14]
openssl/jammy-updates 3.0.2-0ubuntu1.14 amd64 [upgradable from: 3.0.2-0ubuntu1.13]

apt update contacted each repository, downloaded the latest index files, and reported that five packages have newer versions available. apt list --upgradable then reads that local index (no network access needed) and prints exactly which packages and versions are involved. Nothing has been installed yet – the system is unchanged until you run upgrade.

Example 2: Install a package

sudo apt install curl

Output:

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  curl
0 upgraded, 1 newly installed, 0 to remove and 4 not upgraded.
Need to get 226 kB of archives.
After this operation, 615 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 curl amd64 7.81.0-1ubuntu1.15 [226 kB]
Fetched 226 kB in 0s (1,024 kB/s)
Selecting previously unselected package curl.
(Reading database ... 184291 files and directories currently installed.)
Preparing to unpack .../curl_7.81.0-1ubuntu1.15_amd64.deb ...
Unpacking curl (7.81.0-1ubuntu1.15) ...
Setting up curl (7.81.0-1ubuntu1.15) ...

APT looked up curl in its index, found it had no unmet dependencies beyond what’s already installed, downloaded the .deb to /var/cache/apt/archives/, and handed it to dpkg, which unpacked the files and ran the package’s setup step. The summary line (0 upgraded, 1 newly installed...) is worth reading every time – it’s your chance to notice if a command is about to remove something you didn’t expect.

Example 3: Removing a package properly – remove vs purge

sudo apt purge nginx
sudo apt autoremove

Output:

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages will be REMOVED:
  nginx*
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
After this operation, 3,481 kB disk space will be freed.
(Reading database ... 184320 files and directories currently installed.)
Removing nginx (1.18.0-6ubuntu14.4) ...
Purging configuration files for nginx (1.18.0-6ubuntu14.4) ...
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.

apt remove nginx would have uninstalled the nginx binaries and stopped its service, but left files like /etc/nginx/nginx.conf on disk in case you reinstall later. apt purge goes further and deletes those configuration files too – use it when you want a completely clean uninstall. autoremove then cleans up any packages that were pulled in only as a dependency of nginx and are no longer needed by anything else.

Example 4: Researching a package before installing it

apt search "text editor"
apt show vim

Output:

Sorting... Done
Full Text Search... Done
vim/jammy-updates 2:8.2.3995-1ubuntu2.15 amd64
  Vi IMproved - enhanced vi editor

nano/jammy 6.2-1 amd64
  small, friendly text editor inspired by Pico

Package: vim
Version: 2:8.2.3995-1ubuntu2.15
Depends: vim-common (= 2:8.2.3995-1ubuntu2.15), vim-runtime (= 2:8.2.3995-1ubuntu2.15), libc6 (>= 2.34), libgpm2, libtinfo6 (>= 6)
Download-Size: 1,268 kB
Description: Vi IMproved - enhanced vi editor

apt search scans package names and short descriptions in the local index for a matching term – no installation, no network round trip. apt show prints full metadata for a specific package, including its exact dependency list and download size, so you know what you’re agreeing to before running install.

How It Works, Step by Step

When you run sudo apt install nginx, this is roughly what happens:

  1. APT reads the local package index (built by the last apt update) to find nginx and every package it depends on.
  2. It computes the full set of packages that need to be installed, upgraded, or (in rare conflict cases) removed to satisfy those dependencies.
  3. It prints a summary of that plan and asks for confirmation (unless you passed -y).
  4. It downloads each required .deb file from the repository into /var/cache/apt/archives/.
  5. It hands the downloaded files to dpkg in dependency order – a package is never unpacked before the packages it depends on.
  6. dpkg unpacks each package’s files onto the filesystem, then runs its post-install script (for nginx, this typically registers and can start a systemd service).

Common Mistakes

Mistake 1: Forgetting sudo

apt install curl

Output:

E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?

APT needs to write to the package database, which is owned by root. Run mutating commands with sudo:

sudo apt install curl

Mistake 2: Assuming remove fully uninstalls a package

sudo apt remove nginx
dpkg -l | grep nginx

Output:

rc  nginx  1.18.0-6ubuntu14.4  amd64  small, powerful, scalable web/proxy server

The leading rc means “removed, config files remain” – /etc/nginx/ is still on disk. If you wanted a clean slate, purge instead:

sudo apt purge nginx

Mistake 3: Relying on apt’s output inside scripts

apt list --installed

Output:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Listing...
adduser/jammy,now 3.118ubuntu5 all [installed]
apt/jammy,now 2.4.13 amd64 [installed]

APT itself warns you here. For anything you plan to parse or run unattended (cron jobs, provisioning scripts, CI), use apt-get and dpkg-query instead, whose output format is guaranteed stable:

dpkg-query -W -f='${binary:Package} ${Version}\n'

Best Practices

  • Run sudo apt update before installing or upgrading anything on a system you haven’t touched recently, so you’re working from a current package index.
  • Review the summary line APT prints before confirming – especially watch for packages listed “to remove” that you didn’t expect.
  • Use apt purge instead of apt remove when you want configuration files gone too, and follow up with apt autoremove to clean up orphaned dependencies.
  • Prefer apt-get and apt-cache over apt in shell scripts and cron jobs, since their output is stable and documented.
  • Use apt show <package> to inspect dependencies and download size before installing something unfamiliar.
  • Only add third-party repositories (via /etc/apt/sources.list.d/) from sources you trust – anything listed there can run code as root during package installation.
  • If a previous APT operation was interrupted and packages are left half-configured, run sudo apt --fix-broken install before trying anything else.

Practice Exercises

  • On a Debian or Ubuntu machine (or a container), run sudo apt update followed by apt list --upgradable. How many packages are upgradable, and which one has the largest download size according to apt show?
  • Install the httpie package, use it to make a request, then remove it with apt remove and check with dpkg -l | grep httpie whether configuration files remain. Purge it and check again.
  • Before installing docker.io, run apt show docker.io to see its dependency list. Which packages would be pulled in that you didn’t expect?

Summary

  • APT is a high-level package manager that wraps dpkg, adding repository management, dependency resolution, and downloads.
  • apt update refreshes the local package index only – it never installs or upgrades anything by itself.
  • apt upgrade updates existing packages without adding or removing any; apt full-upgrade will add or remove packages if that’s required.
  • apt remove keeps configuration files; apt purge deletes them too.
  • Mutating commands need sudo because they write to root-owned system directories and the package database lock.
  • Use apt interactively; use apt-get/apt-cache in scripts, since APT’s own docs warn that apt‘s interface can change.
  • On RHEL/Fedora, dnf (or yum) plays the same role as APT.