How to Install Software on Ubuntu Server (apt, PPAs, .deb Files and Snap Explained)

Beyond apt install: Repos, .deb files, holds, rollbacks, snap.

sudo apt install covers most of what you'll ever need, because Ubuntu's repositories hold tens of thousands of packages. But sooner or later a project says "add our repository", a download comes as a .deb, an update breaks something and you want the old version back, or a guide uses snap. Here's each of those, done properly.

Quick reference

TaskCommand
Searchapt search keyword / apt show package
Install / remove / purge config toosudo apt install x / remove x / purge x
Install a downloaded .debsudo apt install ./file.deb
Which package owns a filedpkg -S /usr/bin/thing
What's installed`apt list --installedgrep name`
Freeze a versionsudo apt-mark hold package
Go back a versionsudo apt install package=1.2.3-1
Add a repository (modern)keyring in /etc/apt/keyrings/, source in /etc/apt/sources.list.d/

1. Finding things

apt search "media server"
apt show jellyfin
apt list --installed | grep nginx
dpkg -S /usr/sbin/nginx # which package put this file here
dpkg -L nginx-common | head # which files a package installed

2. Install, remove, purge

sudo apt install htop
sudo apt remove htop # keeps config files
sudo apt purge htop # removes config files too
sudo apt autoremove # removes dependencies nothing needs now

3. A downloaded .deb

Many projects (Tailscale, VS Code, Plex, Chrome) offer a .deb:

curl -LO https://example.com/thing_1.2.3_amd64.deb
sudo apt install ./thing_1.2.3_amd64.deb

Use apt install ./file, not dpkg -i — apt pulls in missing dependencies, dpkg doesn't. The ./ matters.

4. Adding a third-party repository (the modern way)

The old apt-key add is deprecated. The current pattern, which every serious project now documents, is: key into /etc/apt/keyrings, a source file that references it.

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://example.com/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg
echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/apt stable main" | sudo tee /etc/apt/sources.list.d/example.list
sudo apt update
sudo apt install example

Copy the project's own lines rather than guessing the URL. To remove the repository later, delete the two files and apt update.

PPAs (Launchpad personal archives) are the Ubuntu-specific shortcut: sudo add-apt-repository ppa:name/ppa. Fine for desktop tools; on a server, prefer the project's official repository if it has one.

5. Hold a package at its current version

When an update of one package breaks something (a kernel on odd hardware, a Docker release):

sudo apt-mark hold docker-ce
sudo apt-mark showhold
sudo apt-mark unhold docker-ce

Held packages are skipped by apt upgrade and unattended-upgrades.

6. Roll back to an earlier version

apt list -a nginx # versions available
sudo apt install nginx=1.24.0-2ubuntu7
sudo apt-mark hold nginx

Only versions still in a repository can be installed this way. /var/cache/apt/archives/ may hold the previous .deb if you haven't run apt clean: sudo apt install ./var/cache/apt/archives/nginx_old.deb.

7. Snap: when and when not

Snap packages are self-contained and auto-update. Good for a quick sudo snap install certbot --classic if the apt version is old. Less good on a small server: each snap bundles its own libraries (disk and RAM), updates happen on the snap's schedule, and the /snap/... mounts clutter df. Rule of thumb: apt if it exists there, Docker for services, snap when neither works.

Keep snaps lean: sudo snap set system refresh.retain=2 and sudo snap set system refresh.timer=4:00-6:00.

Troubleshooting

"The repository ... does not have a Release file." The URL or distribution name (noble, jammy) is wrong for your Ubuntu version: lsb_release -cs shows yours.

"NO_PUBKEY". The signing key isn't installed, or the signed-by= path is wrong.

"Unable to correct problems, you have held broken packages." Two sources want different versions. apt policy package shows where each comes from; remove the stray repository.

A .deb needs a library that doesn't exist. It was built for a different Ubuntu release. Look for a version matching yours, or use Docker.

Wrapping up

apt for nearly everything, apt install ./file.deb for downloads, the keyrings pattern for third-party repositories, apt-mark hold when an update bites, and snap only as a last resort. Knowing where a package came from is most of what keeps a server easy to maintain.

Call us