Packages: install, update and trust software
How apt and dnf install software with its dependencies, where packages come from, how to update a server safely, find what owns a file, pin versions, and when snap fits.
By the end of this lesson you'll be able to
0 of 6 completeHow a package manager works
A package is a program bundled with its files, its configuration and a list of what it needs to run. A repository is a server full of packages, published by your distribution or a vendor. The package manager downloads the right packages, installs what they depend on, and remembers every file it put on disk, so it can update or remove them cleanly later.
Two families cover almost every server:
| Debian, Ubuntu | RHEL, Rocky, Alma, Fedora, Amazon Linux | |
|---|---|---|
| Package file | .deb | .rpm |
| High level (repositories, dependencies) | apt (apt-get, apt-cache in scripts) | dnf (yum on older systems) |
| Low level (one package file) | dpkg | rpm |
| Repositories | /etc/apt/sources.list.d/ | /etc/yum.repos.d/ |
Use the high-level tool almost always. dpkg -i file.deb or rpm -i file.rpm install one file and
don't fetch its dependencies, which is how servers end up half-broken.
Everyday commands
| Task | apt (Debian, Ubuntu) | dnf (RHEL family) |
|---|---|---|
| Refresh the lists | sudo apt update | (automatic; sudo dnf makecache) |
| Search | apt search nginx | dnf search nginx |
| Details | apt show nginx | dnf info nginx |
| Install | sudo apt install nginx | sudo dnf install nginx |
| Remove | sudo apt remove nginx | sudo dnf remove nginx |
| Remove with its config | sudo apt purge nginx | (config files are kept as .rpmsave) |
| Upgrade everything | sudo apt upgrade | sudo dnf upgrade |
| Remove unused dependencies | sudo apt autoremove | sudo dnf autoremove |
$ apt-cache policy curl # installed version, and the version apt would install curl: Installed: 8.18.0-1ubuntu2.7 Candidate: 8.18.0-1ubuntu2.7 $ apt-get -s install tree # -s: simulate. Shows what would happen, changes nothing The following NEW packages will be installed: tree 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. $ sudo apt install -y tree # -y: don't ask (for scripts)
sudo apt install -y treesudorun the next command as rootaptDebian/Ubuntu package manager
apt is for people: progress bars and colour. In scripts, use apt-get and apt-cache: their
output stays stable between versions. Set DEBIAN_FRONTEND=noninteractive so no package stops a
script to ask a question.
What's installed, and who owns this file?
$ dpkg -l | grep -c '^ii' # how many packages are installed 549 $ dpkg -l curl # one package: ii = installed ii curl 8.18.0-1ubuntu2.7 amd64 command line tool for transferring data $ dpkg -S /usr/bin/curl # which package put this file here? curl: /usr/bin/curl $ dpkg -L curl # every file a package installed $ apt list --upgradable # what has a newer version waiting $ rpm -qa | sort # RHEL family: everything installed $ rpm -qf /usr/sbin/nginx # RHEL family: which package owns a file
dpkg -l | grep -c '^ii'|pipe: send output to the next commandgrepfind lines that match a pattern-ccount matching lines
apt list --upgradableaptDebian/Ubuntu package manager
rpm -qa | sortsortsort lines
dpkg -S and rpm -qf answer the classic question "where did this binary come from?", which
matters when two versions of a tool are installed and the wrong one runs.
Repositories and trust
Your distribution's repositories have most of what you need. For newer versions of some tools (Docker, PostgreSQL, Node.js, Terraform), vendors publish their own. Adding one is two steps: trust the vendor's signing key, then add the repository and say which key it uses:
$ sudo install -d -m 0755 /etc/apt/keyrings $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null $ echo "deb [signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt update
sudo install -d -m 0755 /etc/apt/keyringssudorun the next command as root
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/nullcurlmake an HTTP request|pipe: send output to the next commandteewrite input to a file and pass it on>write output to a file, replacing it
echo "deb [signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \echoprint text
sudo apt updateaptDebian/Ubuntu package manager
signed-by= ties that repository to that key only, so a key you add for Docker can't be used to
sign packages pretending to be Ubuntu's. Every package is checked against the key before it's
installed.
Updating a production server
Updates fix security holes, so servers must get them. They also change software under running apps, so do it on purpose:
$ sudo apt update && apt list --upgradable # 1. see what would change $ sudo apt-mark hold postgresql-16 # 2. hold anything that needs a planned window $ sudo apt upgrade # 3. upgrade the rest $ ls /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required.pkgs # 4. kernel update? $ sudo apt-mark unhold postgresql-16 # when its window comes
sudo apt update && apt list --upgradablesudorun the next command as rootaptDebian/Ubuntu package manager&&run the next command only if this one worked
ls /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required.pkgslslist filescatprint a file
| Command | Upgrades | Removes or adds packages |
|---|---|---|
apt upgrade | everything that can be upgraded safely | never removes |
apt full-upgrade | also changes that need adding or removing packages | may remove |
dnf upgrade | everything | may replace packages |
Test upgrades on a staging server first, upgrade one production server at a time behind a load
balancer, and keep unattended-upgrades for security fixes only, so urgent patches still apply
by themselves.
snap and other installers
snap packages (Ubuntu) bundle a program with all its dependencies and update themselves. They're
convenient for desktop and developer tools (sudo snap install --classic code), and some
Ubuntu server tools ship this way. On servers, prefer the distribution's packages or the vendor's
repository: they integrate with systemd and your normal update process.
Some tools ship as a single binary (kubectl, terraform) or a vendor install script. Download
them from the official site, check the published checksum (sha256sum -c, from the Text
processing lesson), and put them in /usr/local/bin, which is for software the package manager
doesn't manage.
Audit a server's packages before a change
Before upgrading a server, you want to know where its software comes from. Record which repositories it uses, how many packages are installed, what would be upgraded, and which package provides the curl binary. Save it to one report.
~/packages.txtReveal one safe solution
$ cat > ~/packages-report.sh <<'EOF' #!/bin/bash echo "== repositories"; grep -rh "^URIs\|^deb " /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null | sort -u echo "== installed: $(dpkg -l | grep -c '^ii') packages" echo "== upgradable"; apt list --upgradable 2>/dev/null | tail -n +2 echo "== held"; apt-mark showhold echo "== curl comes from"; dpkg -S "$(command -v curl)" EOF $ bash ~/packages-report.sh > ~/packages.txt $ cat ~/packages.txt == repositories URIs: http://archive.ubuntu.com/ubuntu/ URIs: http://security.ubuntu.com/ubuntu/ == installed: 549 packages == upgradable == held == curl comes from curl: /usr/bin/curl
cat > ~/packages-report.sh <<'EOF'catprint a file>write output to a file, replacing it
Newer Ubuntu releases describe repositories in .sources files (URIs: lines); older ones use
one-line deb … entries. The script reads both. An empty "upgradable" list right after apt update means the server is current.
Try it yourself
0 of 6 steps doneRun each task in your own account or terminal, then tick it off.
Quick check
apt install says "Unable to locate package" for a package you know exists. What do you run first?
Official reading for this lesson
Or get every quiz answer right and it completes itself.