Search…
Linux from Scratch · Part 10

Package management and software installation

In this series (15 parts)
  1. What is Linux and how it differs from other OSes
  2. Installing Linux and setting up your environment
  3. The Linux filesystem explained
  4. Users, groups, and permissions
  5. Essential command line tools
  6. Shell scripting fundamentals
  7. Processes and job control
  8. Standard I/O, pipes, and redirection
  9. The Linux networking stack
  10. Package management and software installation
  11. Disk management and filesystems
  12. Logs and system monitoring
  13. SSH and remote access
  14. Cron jobs and task scheduling
  15. Linux security basics for sysadmins

Package managers are what make Linux practical. Instead of downloading installers from random websites, you run one command and the system downloads, verifies, installs, and configures software for you. It also handles dependencies, so when you install program A that needs library B, library B gets installed automatically.

Prerequisites

You should have a working Linux environment and be comfortable with command line tools.

How package management works

Every distribution maintains repositories, which are servers hosting thousands of pre-built packages. When you run apt install nginx, the system:

  1. Checks the local package database for nginx
  2. Resolves dependencies (what other packages does nginx need?)
  3. Downloads nginx and all dependencies from the repository
  4. Verifies package integrity using GPG signatures
  5. Unpacks and installs the files to the correct locations
  6. Runs any post-install scripts (creating users, starting services)

apt/dpkg (Debian, Ubuntu)

apt is the high-level package manager. dpkg is the low-level tool that actually installs .deb files. You will use apt 95% of the time.

Essential apt commands

# Update the package list (check for new versions)
sudo apt update

Output:

Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 http://archive.ubuntu.com/ubuntu noble-updates InRelease [89.7 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [89.7 kB]
Fetched 179 kB in 1s (179 kB/s)
Reading package lists... Done
Building dependency tree... Done
45 packages can be upgraded. Run 'apt list --upgradable' to see them.
# Upgrade all packages
sudo apt upgrade -y

# Install a package
sudo apt install nginx

# Remove a package (keeps config files)
sudo apt remove nginx

# Remove a package and its config files
sudo apt purge nginx

# Remove unused dependencies
sudo apt autoremove

# Search for packages
apt search "web server"

# Show package details
apt show nginx

Output of apt show nginx:

Package: nginx
Version: 1.24.0-2ubuntu1
Priority: optional
Section: httpd
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Installed-Size: 48.0 kB
Depends: nginx-core (= 1.24.0-2ubuntu1) | nginx-full (= 1.24.0-2ubuntu1)
Description: small, powerful, scalable web/proxy server

dpkg for .deb files

Sometimes you download a .deb file directly (like for Chrome or VS Code):

# Install a .deb file
sudo dpkg -i package.deb

# If dependencies are missing, fix them
sudo apt install -f

# List files installed by a package
dpkg -L nginx

# Find which package owns a file
dpkg -S /usr/sbin/nginx

Output:

nginx-core: /usr/sbin/nginx

Pinning and holding packages

Sometimes you want to prevent a package from being upgraded (for example, a database server during a migration):

# Hold a package at its current version
sudo apt-mark hold postgresql-16

# Show held packages
apt-mark showhold

Output:

postgresql-16
# Remove the hold
sudo apt-mark unhold postgresql-16

rpm/dnf (Fedora, RHEL, CentOS)

dnf is the high-level manager. rpm is the low-level tool for .rpm files.

# Update package list and upgrade
sudo dnf upgrade

# Install a package
sudo dnf install nginx

# Remove a package
sudo dnf remove nginx

# Search
dnf search "web server"

# Show package info
dnf info nginx

# List installed packages
dnf list installed | head -10

# Install a .rpm file
sudo rpm -i package.rpm

# Find which package owns a file
rpm -qf /usr/sbin/nginx

DNF version locking

# Install the versionlock plugin
sudo dnf install dnf-plugin-versionlock

# Lock a package version
sudo dnf versionlock add postgresql

# List locked packages
dnf versionlock list

# Remove a lock
sudo dnf versionlock delete postgresql

pacman (Arch Linux)

# Update and upgrade everything
sudo pacman -Syu

# Install a package
sudo pacman -S nginx

# Remove a package and its unused dependencies
sudo pacman -Rs nginx

# Search for a package
pacman -Ss "web server"

# Show package info
pacman -Si nginx

# List files in an installed package
pacman -Ql nginx

# Find which package owns a file
pacman -Qo /usr/bin/nginx

Building from source

Sometimes a package is not in the repositories, or you need a specific version with custom options. Building from source means downloading the source code and compiling it yourself.

Prerequisites for building

# On Ubuntu/Debian
sudo apt install build-essential

# On Fedora
sudo dnf groupinstall "Development Tools"

# On Arch
sudo pacman -S base-devel

Example 1: Install, inspect, and remove a package

Let’s walk through the full lifecycle of a package using htop as an example:

# Check if htop is installed
which htop

Output:

# (no output means it's not installed)
# Search for it
apt search htop

Output:

htop/noble 3.3.0-4 amd64
  interactive processes viewer
# Install it
sudo apt install -y htop

Output:

Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  htop
0 upgraded, 1 newly installed, 0 to remove and 0 not to upgrade.
Need to get 172 kB of archives.
...
Setting up htop (3.3.0-4) ...
# Verify installation
which htop
htop --version

Output:

/usr/bin/htop
htop 3.3.0
# See what files the package installed
dpkg -L htop

Output:

/.
/usr
/usr/bin
/usr/bin/htop
/usr/share
/usr/share/applications
/usr/share/applications/htop.desktop
/usr/share/doc
/usr/share/doc/htop
/usr/share/doc/htop/changelog.Debian.gz
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/htop.1.gz
/usr/share/pixmaps
/usr/share/pixmaps/htop.png
# Check how much disk space it uses
apt show htop 2>/dev/null | grep "Installed-Size"

Output:

Installed-Size: 373 kB
# Remove it completely
sudo apt purge -y htop
sudo apt autoremove -y

# Verify it's gone
which htop

Output:

# (no output, successfully removed)

Example 2: Build a simple C program from source

Let’s build jq (a JSON processor) from source to see the full build-from-source workflow:

# Install build dependencies
sudo apt install -y build-essential autoconf automake libtool git

# Clone the source code
git clone https://github.com/jqlang/jq.git /tmp/jq-build
cd /tmp/jq-build

# Check out a specific version
git checkout jq-1.7.1

# Look at the build instructions
ls

Output:

AUTHORS  COPYING  Makefile.am  README.md  configure.ac  src/  tests/  ...
# Generate the configure script
git submodule update --init
autoreconf -i
# Configure the build (check available options)
./configure --help | head -20

Output:

`configure' configures jq 1.7.1 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [/usr/local]
# Configure with default settings
./configure --prefix=/usr/local

Output:

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
config.status: creating Makefile
config.status: executing depfiles commands
# Build (use -j to parallelize with number of CPU cores)
make -j$(nproc)

Output:

...
  CC       src/main.o
  CC       src/jv.o
  CC       src/execute.o
...
  CCLD     jq
# Test the build
./jq --version

Output:

jq-1.7.1
# Install to /usr/local
sudo make install

# Verify
which jq
jq --version

Output:

/usr/local/bin/jq
jq-1.7.1
# Clean up source
cd ~ && rm -rf /tmp/jq-build

If you want to uninstall something built from source, you need the source directory. Run sudo make uninstall from it. This is one reason package managers are preferred: they track every installed file.

Snap vs Flatpak

Both are universal package formats that work across distributions.

FeatureSnapFlatpak
Developed byCanonical (Ubuntu)Community / Red Hat
SandboxingYesYes
Auto-updatesYesConfigurable
SizeLarger (bundles dependencies)Shared runtimes
Available onAll distros, default on UbuntuAll distros
CLI toolsnapflatpak
# Install a snap
sudo snap install vlc

# List snaps
snap list

# Install a flatpak
flatpak install flathub org.videolan.VLC

# List flatpaks
flatpak list

For server software, stick with your distro’s native package manager. Snap and Flatpak are better suited for desktop applications.

What comes next

The next article covers Disk management and filesystems, where you will learn about partitioning, formatting, mounting, and LVM.

For the security implications of package management (verifying package integrity, supply chain attacks), see Linux security basics.

Start typing to search across all content
navigate Enter open Esc close