Package Management: Linux Had an App Store First

At the end of the permissions post I promised we would stop poking at software that is already on the machine and start adding our own. Here is where the Windows muscle memory has to go quietly out the back: on Windows, “installing something” means finding a website, downloading a .exe, and clicking Next → Next → Finish while squinting at the pre-ticked box that also wants to install a browser toolbar from 2009. Linux almost never works that way. It had a curated, signed, dependency-aware software repository — an app store, essentially — a good decade before your phone did. Once you see how it fits together, trawling the web for installers starts to feel faintly barbaric.

One idea: ask the librarian, do not raid the shelves

The mental model that makes everything else click: you do not really install software on Linux so much as ask a very particular librarian to fetch it for you. You name what you want — “I would like GIMP, please” — and the librarian goes off, finds it on a trusted shelf, notices it depends on a dozen other things, fetches all of those too, checks none of them are forgeries, puts everything where it belongs, and writes the whole lot down so it can cleanly take it all back later. That librarian is the package manager, and it is the single most Linux thing about Linux.

What is actually in a “package”

A package is not just a zip of files, though there is a zip of files in there. It is the software plus a manifest: what it is called, what version it is, who built it, a list of every other package it needs to function, and sometimes small scripts to run on install and removal — create a user here, restart a service there. Think of it less as a folder and more as a flat-pack wardrobe that arrives with its instructions, its parts list, and a note reading “you will also need the shelf brackets from box 14.”

Tidbit: the two big package formats

.deb (Debian, Ubuntu, and their many descendants) and .rpm (Red Hat, Alma, Rocky, Fedora, SUSE). Different container formats, same idea; Arch does its own thing with a simpler tarball. You rarely touch these files directly — the package manager does — but when someone hands you a lone .deb to install, that is what it is: one piece of furniture and no librarian, so you become responsible for its dependencies. More on why that is a trap shortly.

Repositories: shelves someone vouches for

The “trusted shelf” is not a metaphor doing nothing. A repository is a collection of packages hosted somewhere your distribution vouches for, and — this is the quiet security story of the entire system — everything on it is cryptographically signed. Your machine ships knowing the distro’s signing keys, so when it pulls a package it can check the signature and refuse anything that has been tampered with or arrived from the wrong place. You are installing from a proper bookshop with a name over the door, not buying a DVD from a bloke with a holdall at the station.

This is the bit people coming from Windows tend to underestimate. On Linux the default path — the one that is least effort — is also the most secure: signed packages from a curated repo. You have to go slightly out of your way to do the risky thing, which is rather the whole point.

Dependencies, and the citation chain

Here is the problem the package manager quietly solves for you a hundred times a day. Almost no program is self-contained; it leans on shared libraries, which lean on other libraries, all the way down. Ask for one modest image editor and the real shopping list looks like this:

flowchart TD
  A["You: install gimp"] --> B["needs libgtk"]
  B --> C["needs libglib"]
  B --> D["needs libpango"]
  D --> E["needs libfreetype"]
  C --> F["dozens more, each with their own"]

Working that out by hand would be a lost afternoon and a headache. The package manager reads every manifest, assembles the complete chain, and installs it in the right order without you ever seeing the machinery. Old hands will remember when this went wrong — “dependency hell”, where package A wanted version 1 of a library and package B demanded version 2 and no arrangement satisfied both. Modern resolvers have very largely tamed it, which is why you can go years now without meeting the phrase.

Same idea, different words

Back in the distro post we met the big families. The thing that most visibly separates them day to day is which package manager they hand you — but they all do the same handful of jobs, just spelled differently:

TaskDebian / Ubuntu — aptAlma / RHEL / Fedora — dnfArch — pacman
Install a packagesudo apt install foosudo dnf install foosudo pacman -S foo
Remove itsudo apt remove foosudo dnf remove foosudo pacman -R foo
Refresh the cataloguesudo apt updatesudo dnf check-updatesudo pacman -Sy
Upgrade everythingsudo apt upgradesudo dnf upgradesudo pacman -Syu
Search for somethingapt search foodnf search foopacman -Ss foo

Learn the shape once and you can find your footing on any of them. The rest — clearing caches, listing what is installed, pinning versions, working out which package owns a given file — lives in the Package Manager Cheatsheet, so you do not have to keep three sets of flags in your head at once.

update vs upgrade — the one that catches everyone

On the Debian side especially there is a trap worth burning in early, because the two words sound interchangeable and absolutely are not. apt update does not update your software. It refreshes the catalogue — it goes and asks each repository “what is the latest version of everything now?” and writes the answers down. Nothing on your system actually changes yet. It is apt upgrade that then takes that refreshed list and installs the newer versions.

$ sudo apt update
Hit:1 http://deb.debian.org/debian bookworm InRelease
Get:2 http://security.debian.org bookworm-security InRelease
Fetched 8,192 kB in 2s (4,096 kB/s)
12 packages can be upgraded. Run 'apt list --upgradable' to see them.

$ sudo apt upgrade
The following packages will be upgraded:
  curl libssl3 openssh-server tzdata
Do you want to continue? [Y/n]

So the ritual is almost always the pair, in order: refresh the catalogue, then upgrade against it. Run upgrade on a stale catalogue and you will dutifully install yesterday’s idea of “latest”. (dnf and pacman fold the two together more, which is why pacman -Syu — sync, refresh, upgrade — is a single incantation Arch users type in their sleep.)

The modern wrinkle: packages that bring their own everything

The classic model shares libraries: install libssl once and forty programs use the same copy. Efficient, tidy, and occasionally maddening when two of those programs want different versions of it. So a newer breed of “universal” package makes the opposite bet — bundle everything the app needs inside the package itself and sandbox it from the rest of the system. The three you will meet: Snap (Canonical’s, the default on Ubuntu), Flatpak (the cross-distro favourite, big in the desktop world), and AppImage (a single file you make executable and run, no installer at all).

What you buy is convenience and isolation: the same package runs on any distro, and a dodgy app cannot easily rifle through your whole home directory. What you pay is size and speed — ten apps that each bring their own copy of the same libraries is a great deal of duplicated disk, and sandboxed apps start a beat slower. For servers I still reach for the native package manager nearly every time; on the desktop, Flatpak has genuinely earned its place. Horses for courses.

The trust bit, or: why sysadmins wince at curl | bash

Warning

You will eventually meet install instructions that read curl https://example.com/install.sh | sudo bash. Stop and appreciate what that asks of you: download a script from a URL whose contents you cannot see, and run it as root, sight unseen. If that server has been compromised, or the URL is a near-miss typo of the real one, you have just handed the whole machine to a stranger. Sometimes it genuinely is the vendor’s only option — but treat it the way you would treat someone asking to hold your keys “just for a sec”. Download it first (curl … -o install.sh), read it, then run it — or better, check whether there is a signed package in a real repo instead.

The same caution scales down to third-party repositories and Ubuntu’s PPAs. They are useful — sometimes essential, for software newer than your distro ships — but every one you add is another party you have decided to trust with root-level installs on your machine, and unlike the official repo, nobody is vetting it but you. Add them deliberately, from sources you would vouch for, and remember what you have added. The convenience of the van out the back is real; so is the reason your distro does not stock its shelves that way.

The one-sentence version

Software on Linux comes from signed, trusted repositories through a package manager that works out the entire dependency chain for you; you refresh the catalogue (update) then install against it (upgrade), the commands are the same few ideas in apt, dnf or pacman spelling, and the only real discipline is caution about anything from outside that trusted shelf. The full command matrix is in the Package Manager Cheatsheet.

We now have a machine we can navigate, control and keep stocked with software. The thing we have not done is make it actually do anything on its own — run a web server, restart itself after a crash, start things in the right order at boot. That is the job of the init system, and on almost every modern Linux that means systemd. Next time: services, units, and teaching Linux to keep something running whether you are watching or not.