= Package management with dnf

Installing an application on a computer system is technically pretty simple: you copy files from an archive (like a ZIP file) onto the target computer in a place the operating system expects there to be applications.
Because many of us have become accustomed to having fancy installer "wizards" to help us get software on our computers, the process seems like it should be more complex than it is.
What's actually complex, though, is the issue of what exactly makes up a single application.
What we users think of as a single application actually contains code borrowing from software libraries (`.so` files on Linux, .dll` files on Windows, `.dylib` on MacOS) scattered throughout an operating system.
So that users don't have to worry about that veritable matrix of inter-dependent code, Linux uses a *package management* system to track what application needs what library, and which library or application has security or feature updates, and what extra data files got installed with each software title.
A package manager is, essentially, an installer wizard.
They're easy to use, they provide both graphical interfaces and terminal-based interfaces, and they make your life easier.
The better you know your distribution's package manager, the easier your life gets.

<!-- not for article. For ebook only.

Long before Red Hat was Red Hat Enterprise Linux (RHEL), its developers recognized the need to track what files got installed when a user added an application to a system.
The solution was the *RPM Package Manager* (RPM).
RPM is listed in the Linux Standards Base (LSB) as the standard Linux packaging format, it's the default or supported packaging format for several Linux distributions, and it has a well-supported toolchain to help developers deliver their applications in a consistent, predictable, and automatable way.
However, the `rpm` command itself is rarely used, in favour of the friendly front-end `dnf` (formerly `yum`) command.

The `dnf` command is used by RHEL, CentOS, Fedora, Mageia, OpenMandriva, and others to install, remove, update, and manage software.

-->

== Installing applications on Linux

If you're a casual desktop user who wants to install an application on Linux, then you may be looking for *GNOME Software*, a desktop application browser.

image: gnome-software.jpg

It works as you'd expect: you click through its interface until you find an application that seems like it would be useful, and then you click the *Install* button.

Alternately, you can open `.rpm` or `.flatpakref` packages downloaded from the web in GNOME Software for it to install them for you. 

If you're inclined toward controlling your computer with typed commands, read on!

== Finding software with dnf

Before you can install an application, you may need to confirm that it exists on your distribution's servers.
Usually, searching for the common name of an application with `dnf` suffices.
For instance, say you recently read https://opensource.com/article/20/11/cockpit-server-management[an article about Cockpit] and decide you want to try it, then you could search for `cockpit` to verify that your distribution includes it:

[source, bash]
----
$ dnf search cockpit
 Last metadata expiration check: 0:01:46 ago on Tue 18 May 2021 19:18:15 NZST.
 ==== Name Exactly Matched: cockpit ====
 cockpit.x86_64 : Web Console for Linux servers

==== Name & Summary Matched: cockpit ==
 cockpit-bridge.x86_64 : Cockpit bridge server-side component
 cockpit-composer.noarch : Composer GUI for use with Cockpit
 [...]
----

There's an exact match.
The package listed as a match is called `cockpit.x86_64`, but the `.x86_64` part of the name actually only denotes the CPU architecture it's compatible with.
By default, your system installs packages with matching CPU architectures, so you can ignore that extension, and so you've now confirmed that the package you're looking for is indeed called simply `cockpit`.

Now you can confidently install it with `dnf install`.
This step requires administrative priviledges:

[source, bash]
----
$ sudo dnf install cockpit
----

More often than not, that's the typical `dnf` workflow: search and install.

Sometimes, however, the results of `dnf search` aren't clear to you, or else you just want more information about a package than just its common name.
There are a few relevant `dnf` subcommands, depending on what information you're after.

== Package metadata

If you feel like your search got you _close_ to the package you want, but you're just not sure yet, then it's often helpful to take a look at the package's metadata, such as the project's URL and description.
To get this info, you use the pleasantly intuitive `dnf info` command:

[source, bash]
----
$ dnf info terminator
Available Packages
Name         : terminator
Version      : 1.92
Release      : 2.el8
Architecture : noarch
Size         : 526 k
Source       : terminator-1.92-2.el8.src.rpm
Repository   : epel
Summary      : Store and run multiple GNOME terminals in one window
URL          : https://github.com/gnome-terminator
License      : GPLv2
Description  : Multiple GNOME terminals in one window.  This is a project to produce
             : an efficient way of filling a large area of screen space with
             : terminals. This is done by splitting the window into a resizeable
             : grid of terminals. As such, you can  produce a very flexible
             : arrangements of terminals for different tasks.
----

This info dump tells you the version of the available package, which repository registered with your system provides it, the project's website, and a long description of what it does.

== What package provides a file

Package names don't always match what you're looking for.
For instance, suppose you're reading documentation telling you that you must install something called `qmake-qt5`.

[source, bash]
----
$ dnf search qmake-qt5
No matches found.
----

The `dnf` database is extensive, so you don't have to restrict yourself to searches for exact matches.
You can use the `dnf provides` command to learn whether anything provides what you're looking for as part of some larger package:

[source, bash]
----
$ dnf search qmake-qt5
qt5-qtbase-devel-5.12.5-8.el8.i686 : Development files for qt5-qtbase
Repo        : appstream
Matched from:
Filename    : /usr/bin/qmake-qt5

qt5-qtbase-devel-5.15.2-3.el8.x86_64 : Development files for qt5-qtbase
Repo        : appstream
Matched from:
Filename    : /usr/bin/qmake-qt5
----

This confirms that the application `qmake-qt5` is a part of a package named `qt5-qtbase-devel`.
It also tells you that the application gets installed to `/usr/bin`, so you know exactly where to find it once it's installed.

== What files are included in a package

There are times when I find myself approaching `dnf` from a different angle entirely.
Sometimes, I've already confirmed that an application is installed on my system, I just can't figure out how I got it.
Other times, I know I have a specific package installed, but I'm not clear on what exactly that package has put on my system.

If you ever need to "reverse engineer" a package's payload, you can use the `dnf repoquery` command along with the `--list` option.
This looks at the repository's metadata about a package and returns a list of all files provided by that package:

[source, bash]
----
$ dnf repoquery --list qt5-qtbase-devel
/usr/bin/fixqt4headers.pl
/usr/bin/moc-qt5
/usr/bin/qdbuscpp2xml-qt5
/usr/bin/qdbusxml2cpp-qt5
/usr/bin/qlalr
/usr/bin/qmake-qt5
/usr/bin/qvkgen
/usr/bin/rcc-qt5
[...]
----

These lists can get long, so it helps to pipe the command through `less` or your favorite pager.

== Removing an application

Should you decide you no longer need an application installed on your system, you can use `dnf remove` to uninstall it, all of the files that got installed as part of its package, and any dependencies that are no longer necessary.

[source, bash]
----
$ dnf remove bigapp
----

Sometimes, dependencies get installed along with one app and are later found useful by some other application you install.
In the event that two packages require the same dependency, `dnf remove` does _not_ remove the dependency.
It's not unheard of to end up with a stray package here and there, after installing and uninstalling lots of applications.
Once a year or so, I sometimes perform a `dnf autoremove` to clear out any unused packages:

[source, bash]
----
$ dnf autoremove 
----

This isn't necessary, by any means, but it's a housecleaning step that makes me feel better about my computer.

== Getting to know dnf

The more you know about how your package manager works, the easier it is for you to install and query applications when necessary.
Even if you're not a regular `dnf` user, knowing it can be useful for the times you find yourself interfacing with an RPM-based distro.
Having graduated from `yum`, one of my personal favorite package managers is the `dnf` command, and while I don't love all of its subcommands I do find it one of the more robust of package management systems out there.
LINK-TO-CHEATSHEET[Download our `dnf` cheat sheet] to help yourself get used to the command, and don't be afraid to try some new tricks with it.
Once you get used to it, you might find it hard to use anything else.
