Christian Lehnert — Linux, Hacking & Faith

Appreciate Your Package Manager

Christian Lehnert2026-07-14~5 min read

Appreciate Your Package Manager

Building Linux From Scratch means going without a package manager,
because there is no package manager until you build one, and the
standard LFS book does not have you build one at all. You install
every piece of software by hand: download the source, extract it,
configure it, compile it, run its test suite, install it. Dozens of
packages, in a specific order, each one manually.

Doing this is the fastest way I know to develop a deep appreciation
for the thing that apt install quietly does for you every day.

What You Actually Do Under LFS

When you install a package under LFS, the sequence for each one is
roughly: read the book's page for that package, download the exact
version the book specifies, verify it against the expected checksum
by hand, extract it, read the configure options and understand why
each one is set, run configure, run make, run the test suite and
interpret the results, run make install, and then move on to the
next package, which frequently cannot be built until this one is in
place.

That last clause is the whole game. The order is not arbitrary.
Package B needs package A's libraries and headers present before it
will build. Package C needs both. The LFS book has spent years
getting this order correct so that following it top to bottom works,
and the moment you deviate, add a package out of sequence, skip one
you thought you did not need, upgrade one thing without rebuilding
what depends on it, you discover exactly how much work goes into
knowing what depends on what.

There is no apt install. There is you, the book, and a dependency
graph you are walking by hand.

What the Package Manager Was Doing All Along

Every one of those manual steps is something a package manager
automates, and the automation is far more sophisticated than the
single command it hides behind suggests.

Dependency resolution is the obvious one. apt install nginx
figures out that nginx needs a specific set of libraries, that those
libraries need others, and it computes the full transitive closure
of everything that has to be present, then installs all of it in an
order that works. Under LFS you are the resolver. You hold the graph
in your head or on paper, and you walk it manually, and you feel
every edge.

Ordering falls out of resolution but is worth naming separately. The
package manager does not just know what is needed; it knows what
order to install it in so that each package's dependencies are
present when it lands. This is a topological sort of the dependency
graph, computed instantly, that you performed by hand and by
sequence for every package in your LFS build.

Conflict detection is the one people never think about because they
never see it fire. The package manager knows when two packages
cannot coexist, when installing one would overwrite files owned by
another, when a version requirement is unsatisfiable. Under LFS,
nobody is checking. You overwrite a file, you break a thing, and you
find out at runtime.

File tracking is the quiet miracle. dpkg knows every file that every
package installed. When you remove a package, it removes exactly
those files and no others. Under LFS, make install scatters files
across the filesystem and nothing records where they went. Removing
a package cleanly, or even knowing what a package installed, is a
problem you have to solve yourself, which is why serious LFS builds
eventually adopt a package-user scheme or a DESTDIR-based tracking
hack, reinventing a fraction of what dpkg does.

Upgrades are the compound version of all of the above. Upgrading one
package in a running system means knowing what depends on it,
whether the new version breaks any of them, what files change, and
how to roll back if it goes wrong. apt upgrade does this across a
thousand packages at once. Under LFS, an upgrade is a manual project
with manual risk.

Why Nobody Sees It

The reason almost nobody appreciates their package manager is that a
good package manager is invisible by design. The entire point of apt
and dpkg, of dnf and rpm, of pacman and portage, is to make the
enormous underlying complexity disappear behind a command that just
works. When the abstraction is doing its job, you do not see the
work, which means you do not see how much work there is.

This is the same reason nobody appreciates the toolchain bootstrap
until they do it by hand, or the boot process until they assemble it
from parts. The best infrastructure is the infrastructure you never
have to think about, and the cost of that invisibility is that the
people it serves forget it is there. A package manager that made you
aware of everything it does would be a bad package manager. The
awareness has to come from somewhere else, and LFS is one of the
few places it reliably does.

Closing

I am not suggesting anyone run LFS as a daily driver to stay humble.
Debian exists precisely so I do not have to hand-resolve a dependency
graph every time I want to install a web server, and that is the
correct arrangement. The package manager is one of the great quiet
achievements of the Linux ecosystem, and using it without thinking
about it is exactly what it was built for.

But building a system without one, once, changes how you type apt install forever after. The command that used to feel like nothing
now feels like the tip of an enormous, carefully maintained iceberg
of dependency metadata, ordering logic, conflict rules, and file
tracking, assembled by people who did the hard part so that the rest
of us could type five characters and get a working program.

Next time your package manager resolves a hundred dependencies and
installs them in the right order in three seconds, notice it. Under
LFS, that is a week of careful work. The package manager does it
before you have finished reading the confirmation prompt.

Tagged:
#linux #lfs #apt #package-manager
← Back to posts