apt
Install, remove and update Debian packages
apt is the command you will type more than any other on a Debian system. It resolves
dependencies, fetches packages from the repositories configured in /etc/apt/sources.list.d/,
and hands them to dpkg to unpack and configure, then keeps the whole set consistent as
things change underneath it.
The naming is genuinely confusing, so it is worth being precise. apt is one of several front
ends to the same library: apt-get and apt-cache are
the older, script-stable pair, and apt gathers the most-used parts of both behind one name
with nicer defaults. They are shipped by the same package and share a dependency resolver, so
they never disagree about what should be installed.
apt vs apt-get covers where they do differ.
Underneath sits dpkg, which installs a single .deb file and knows
nothing about repositories, dependencies or where a package came from. Almost every apt command
ends in a dpkg run, which is why dpkg's errors surface through apt.
The two-step model
Nearly every mistake with apt comes from forgetting that it works from a cached copy of what the repositories contain, not from the repositories themselves:
apt updaterefreshes that cache. It changes nothing about what is installed.apt install/apt upgradeact on the cache as it currently stands.
So apt install immediately after a fresh install of Debian, without an apt update first, can
fail to find a package that is right there in the archive, or offer you a version that was
superseded weeks ago. When something is missing or stale, apt update is nearly always the first thing to try.
Debian's release channels covers what those repositories are and
how a package gets into one.
Seeing what will happen first
Every state-changing apt command prints its plan and waits for confirmation. Read the plan rather than skipping to the y/n. It tells you what is about to be installed, upgraded, removed and, the line worth reading twice, what is no longer required.
-s (--simulate, also spelled --dry-run) goes further: it prints the plan and exits without
touching anything, needing no root. Use it whenever a command is going to remove something, or
when you are working from instructions you do not fully trust.
Which one is safe in a script
apt is designed for people. It says so itself: run any apt command with its output piped
somewhere and it prints a warning that its command-line interface is not stable between
versions. In a script, in a Dockerfile, in a systemd unit or in cron, use apt-get and
apt-cache, whose output formats are treated as an interface and kept still. Add -y, set
DEBIAN_FRONTEND=noninteractive, and check the exit status; see
Exit codes and error handling.
Scripts also have to cope with not being the only thing installing packages: on a machine running automatic updates, apt can fail outright because something else holds the dpkg lock. Could not get lock /var/lib/dpkg/lock-frontend explains the timeout that fixes it properly.
Root, and when you don't need it
Anything that changes installed packages needs root, normally through sudo, which on Debian
is not always installed, depending on what you
answered about a root password when you set the machine up. Anything that only reads (search,
show, list, policy, and any --simulate run) does not, and it is worth getting into the
habit of running those unprivileged. The examples below mark which is which.
Finding a package
None of these change anything, so none need sudo. All of them read the local cache built by apt update rather than asking the repositories directly. The examples on this page act on cowsay throughout, because it is small, it is Architecture: all - so its output is identical on every machine - and removing it breaks nothing.
Search for a package by name and description
apt search 'talking cow' | head -6
Full-text search across names and descriptions - neither package here is called "talking cow". It matches generously, so pipe it through head.
Show output
Sorting...
Full Text Search...
cowsay/stable,now 3.03+dfsg2-8 all [installed]
configurable talking cow
cowsay-off/stable 3.03+dfsg2-8 all
Search package names only
apt search --names-only '^cowsay'
Restricts the match to the package name, and takes a regular expression - ^ anchors it to the start. See grep for the syntax.
Show output
Sorting...
Full Text Search...
cowsay/stable,now 3.03+dfsg2-8 all [installed]
configurable talking cow
cowsay-off/stable 3.03+dfsg2-8 all
configurable talking cow (offensive cows)
Read a package's details
apt show cowsay | head -12
Version, size, dependencies and homepage. The full output also ends with the repository it came from and the long description; -a shows every available version rather than just the candidate.
Show output
Package: cowsay
Version: 3.03+dfsg2-8
Priority: optional
Section: games
Maintainer: James McDonald <james@jamesmcdonald.com>
Installed-Size: 94.2 kB
Depends: libtext-charwidth-perl, perl:any
Suggests: filters, cowsay-off
Homepage: https://web.archive.org/web/20120527202447/http://www.nog.net/~tony/warez/cowsay.shtml
Tag: game::toys, implemented-in::perl, interface::commandline, role::program,
use::entertaining, works-with::text
Download-Size: 21.4 kB
Check whether a package is installed
apt list --installed cowsay cowsay-off
Names several packages at once. Only the installed ones are listed, so a package missing from the output is one that isn't installed.
Show output
Listing...
cowsay/stable,now 3.03+dfsg2-8 all [installed]
List installed packages matching a pattern
apt list --installed 'ca-cert*'
Quote the pattern, or the shell tries to expand it as a filename first and apt never sees it.
Show output
Your output will differ: the ca-certificates version changes with each Debian point release
Listing...
ca-certificates/stable,now 20250419 all [installed]
See which version apt would install
apt policy cowsay | head -3
Installed: is what you have and Candidate: is what a plain apt install would give you. The rest of the output lists each available version and the repository offering it.
Show output
cowsay:
Installed: 3.03+dfsg2-8
Candidate: 3.03+dfsg2-8
Find which installed package owns a file
dpkg -S /usr/bin/apt-get
A dpkg query rather than an apt one, because it works from the list of files each installed package shipped. For a file you don't have yet, apt-file search is the equivalent.
Show output
apt: /usr/bin/apt-get
Show what a package depends on
apt depends cowsay
Direct dependencies only. Depends: is required, Recommends: is installed by default on Debian, and Suggests: never is.
Show output
cowsay
Depends: libtext-charwidth-perl
Depends: <perl:any>
perl
Suggests: filters
Suggests: cowsay-off
Seeing what apt will do before it does it
-s (--simulate, or --dry-run) prints the plan and exits without changing anything. It needs no root, which makes it the safe way to read instructions you don't fully trust.
Simulate an install
apt install -s cowsay-off
Shows what would be installed, including dependencies pulled in behind the package you named.
Show output
Your output will differ: the point release in Debian:13.6 and the Not Upgrading count move as the archive does
Reading package lists...
Building dependency tree...
Reading state information...
Installing:
cowsay-off
Summary:
Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 1
Inst cowsay-off (3.03+dfsg2-8 Debian:13.6/stable [all])
Conf cowsay-off (3.03+dfsg2-8 Debian:13.6/stable [all])
Simulate a removal
apt remove -s cowsay
The line to read is anything under REMOVED - this is where an unexpected cascade shows up before it happens rather than after.
Show output
Your output will differ: the point release in Debian:13.6 and the Not Upgrading count move as the archive does
Reading package lists...
Building dependency tree...
Reading state information...
The following packages were automatically installed and are no longer required:
libgdbm-compat4t64 libperl5.40 perl perl-modules-5.40
Use 'apt autoremove' to remove them.
REMOVING:
cowsay
Summary:
Upgrading: 0, Installing: 0, Removing: 1, Not Upgrading: 1
Remv cowsay [3.03+dfsg2-8]
Simulate an install without the recommended extras
apt install -s --no-install-recommends cowsay-off
Debian installs Recommends: by default. Comparing this against the plain simulate above shows exactly what that policy adds.
Show output
Your output will differ: the point release in Debian:13.6 and the Not Upgrading count move as the archive does
Reading package lists...
Building dependency tree...
Reading state information...
Installing:
cowsay-off
Summary:
Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 1
Inst cowsay-off (3.03+dfsg2-8 Debian:13.6/stable [all])
Conf cowsay-off (3.03+dfsg2-8 Debian:13.6/stable [all])
See which packages are no longer needed
apt autoremove -s
Lists packages installed automatically as dependencies that nothing requires any more. Worth reading before running the real thing.
Show output
Your output will differ: the point release in Debian:13.6 and the Not Upgrading count move as the archive does
Reading package lists...
Building dependency tree...
Reading state information...
Summary:
Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 1
Installing packages
All of these need root. -y answers the confirmation prompt in advance, which a script needs and which is worth omitting by hand so you get a chance to read the plan. Their output is a live download - sizes, speeds, and the architecture of your own machine - so it isn't reproduced here.
Install a package
sudo apt install cowsay-off
Fetches the package and everything it depends on, then configures the lot. Prints the plan and waits for confirmation first.
Install several packages in one transaction
sudo apt install -y cowsay-off bash-completion
Naming them together makes it a single transaction, so dependencies are resolved across the whole set and it either all succeeds or all fails.
Install a specific version
sudo apt install cowsay-off=3.03+dfsg2-8
Pins this install to a version apt policy lists. apt refuses if another installed package needs a different one.
Reinstall a package whose files were damaged
sudo apt reinstall cowsay
Unpacks the same version again, restoring files deleted or edited by hand. Configuration files you changed are left alone.
Install without the recommended extras
sudo apt install --no-install-recommends cowsay-off
Keeps the install minimal - sensible in a container image, and on a desktop often removes something you wanted.
Download a package without installing it
apt download cowsay
Drops the .deb in the current directory and needs no root. Useful for moving a package to a machine with no network, or inspecting it before trusting it.
Install a .deb file you already have
sudo apt install ./cowsay_3.03+dfsg2-8_all.deb
Prefer this over dpkg -i, because apt resolves the file's dependencies from the repositories. The ./ matters - without it, apt looks for a package with that name instead. Installing a .deb by hand has the failure mode and the way out of it.
Removing packages
remove and purge differ only in what happens to the configuration in /etc, and that difference is behind most of the "I removed it but it's still configured" confusion. autoremove is not a third strength of the same operation: it acts on packages you never asked for, a distinction pulled apart here.
Remove a package, keeping its configuration
sudo apt remove cowsay
Deletes the programs, leaves the configuration files in place, and the package then shows as rc rather than gone. Reinstalling later picks your settings back up.
Remove a package and its configuration
sudo apt purge cowsay
The complete removal, including the /etc files remove leaves behind.
Finish a removal you meant as a purge
sudo apt purge -y bash-completion
Acts on a package already in the rc state, where the programs are gone but the configuration is not. This is the fix for having run remove when you wanted purge.
Remove packages nothing needs any more
sudo apt autoremove
Deletes packages pulled in as dependencies that are now unreferenced. Read apt autoremove -s first - it occasionally proposes something you installed deliberately.
Keeping the system up to date
Two separate steps, and conflating them is the most common apt mistake. update refreshes the local list of what exists and installs nothing; the upgrade commands act on whatever that list currently says. Their output depends on what Debian has published this week, so it isn't reproduced here either.
Refresh the package lists
sudo apt update
Contacts each configured repository and rebuilds the local cache. Run it before installing on a machine that has been idle, or apt works from stale information.
Upgrade everything that can be upgraded safely
sudo apt upgrade
Installs newer versions of what you already have, and new packages where an upgrade needs them. It never removes anything.
Upgrade, allowing packages to be removed
sudo apt full-upgrade
The same operation as apt-get dist-upgrade. Allowed to remove packages to satisfy a dependency change, which a release upgrade needs and a routine update does not.
List the packages with upgrades waiting
apt list --upgradable
Read-only, so no sudo. Shows the installed version and the candidate side by side - the quickest way to judge whether an upgrade is worth doing now.
Upgrade one package and nothing else
sudo apt install --only-upgrade cowsay
Upgrades just the named package. It often refuses, which is apt telling you the upgrade isn't really a single-package job.
Holds, marks and disk space
Stop a package being upgraded
sudo apt-mark hold cowsay
Pins the installed version until you say otherwise. Held packages are skipped by upgrade and reported as kept back.
Show output
cowsay set on hold.
List every held package
apt-mark showhold
Worth checking when an upgrade refuses to install something for no visible reason - a forgotten hold is a common cause.
Show output
ca-certificates
Release a hold
sudo apt-mark unhold ca-certificates
Returns the package to normal upgrade handling, and says so only if a hold was really in place.
Show output
Canceled hold on ca-certificates.
Mark a package as automatically installed
sudo apt-mark auto cowsay
Tells apt you didn't ask for this one directly, making it eligible for autoremove once nothing depends on it.
Show output
cowsay set to automatically installed.
See how much space the package cache is using
du -sh /var/cache/apt/archives
Answers whether apt clean is worth running, before you run it. See finding the largest files for space elsewhere.
Delete downloaded package files
sudo apt clean
Empties /var/cache/apt/archives. Frees real space on a long-lived machine, and costs only re-downloading anything you reinstall.
Delete only the downloads that are now obsolete
sudo apt autoclean
The conservative clean - drops cached .deb files that can no longer be downloaded, and keeps the current ones.
apt in scripts
Use apt-get and apt-cache here rather than apt: their output is treated as a stable interface and apt's explicitly is not. See apt vs apt-get.
Install with no prompting at all
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y cowsay-off
-y answers apt's own prompt; DEBIAN_FRONTEND=noninteractive stops a package's configuration script opening a dialogue behind it and hanging for ever.
Wait for the dpkg lock instead of failing
sudo apt-get -o DPkg::Lock::Timeout=60 install -y cowsay-off
Waits up to a minute for another apt to finish rather than exiting immediately - the fix for a provisioning script that intermittently fails on a fresh machine. See Could not get lock.
Test whether a package is installed, by exit status
dpkg -s cowsay >/dev/null 2>&1 && echo installed || echo missing
Exit status rather than parsed output, so no formatting change can break it. See Exit codes and error handling.
Show output
installed
Print just the installed version of a package
dpkg-query -W -f='${Version}\n' cowsay
dpkg-query -f is the scriptable way to read package metadata: you name the fields, so nothing else in the output can shift underneath you.
Show output
3.03+dfsg2-8
Fix a half-finished install
sudo apt install -f
Short for --fix-broken. Completes dependency work left unfinished by an interrupted run, and is the first thing to try when apt refuses to do anything else.