LFCA 28 🐧 Installing Packages
Installing packages is the daily work of Linux administration. The previous chapter covered what package managers are and the full set of operations. This chapter is about the install operation specifically — the command, what happens when it runs, how dependency resolution works, the difference between installing from a repository and installing a local file, the flags that matter, and the habits that keep installations clean. It covers apt install on Debian and Ubuntu in detail, because that is the most widely used package manager, and then shows the equivalent commands on Fedora, openSUSE, and Arch. The goal is not just to know the command but to understand what the package manager is doing, why it sometimes refuses, and how to recover when something goes wrong.
Key point: apt install package downloads the package and its dependencies from the repositories, resolves the dependency graph, and installs everything in one transaction. The command requires the local package index to be current, which is why apt update is run first. apt install ./file.deb installs a local .deb file and resolves its dependencies, which dpkg -i does not. A failed install leaves the package database in a state that needs repair, and the repair tools — apt --fix-broken install and dpkg --configure -a — are the recovery mechanism. On other distributions, dnf install, zypper install, and pacman -S do the same thing with different syntax.
What happens when you install a package
The install command is a single line, but the work it triggers is a sequence of steps. Understanding them explains why the command sometimes fails and what the failure means.
The high-level tool reads the local package index — the list of available packages and their versions — and locates the requested package. It reads the package’s metadata, which lists its dependencies: the libraries and programs it needs. It checks which of those dependencies are already installed and which are missing. For the missing ones, it repeats the process, building a complete dependency graph. It then presents a plan: which packages will be installed, upgraded, or removed, and how much disk space the change requires. If the user confirms, it downloads the packages, verifies their checksums and signatures, and hands them to the low-level tool, which unpacks each one, runs its pre-installation scripts, places the files, runs its post-installation scripts, and records the package in the database.
Why the plan is shown before installation. The transaction can install more than the requested package, and it can remove or upgrade packages that were not mentioned. The plan shows exactly what will happen, so the user can abort if the change is not what was intended. The plan is the safety check.
Why the local index must be current. The index is a snapshot of the repository at the last refresh. If it is stale, the version of the package it lists may no longer exist, or the dependencies it lists may have changed. Running apt update refreshes the index and ensures the plan is based on current information.
Why dependency resolution is the hard part. Dependencies can conflict — two packages may require incompatible versions of the same library — and the resolver has to find a combination that satisfies all constraints, or report that none exists. This is a constraint-satisfaction problem, and the resolver is the part of the package manager that solves it. When it fails, the error message describes the conflict.
Why checksums and signatures are verified. A package downloaded from a repository is verified against a checksum and a cryptographic signature. This ensures the package was not corrupted in transit and was signed by the repository’s key. If verification fails, the install is aborted, which protects against tampered packages.
Why the transaction is atomic where possible. The package manager tries to apply the whole plan or none of it. If a download fails partway through, the install is aborted and nothing is changed. If a package fails during configuration, the database is left in a state that indicates the failure, and the repair tools can fix it. The atomicity is not perfect — a failure mid-install can leave a partial state — but the design minimizes the damage.
The install command on Debian and Ubuntu
The command is apt install, and the essential pattern is sudo apt update followed by sudo apt install package.
sudo apt update
sudo apt install nginx
The first command refreshes the index. The second installs the package and its dependencies. The sudo prefix is required because installation writes to system directories.
Installing multiple packages in one command. The packages are listed after install, and they are installed together in a single transaction.
sudo apt install nginx curl git
This is better than three separate commands because the dependency resolution considers all three at once, which can produce a smaller set of changes and avoids re-resolving for each package.
Installing a specific version. A version can be specified with =, which is useful when a newer version has a regression and the previous one should be used.
sudo apt install nginx=1.24.0-1ubuntu1
The available versions can be listed with apt policy nginx, which shows the installed version, the candidate version, and all available versions with their source repositories.
Simulating the install. The -s or --simulate flag shows the plan without applying it, which is useful for checking what a command will do before running it.
apt install -s nginx
The output is the same plan that the real command would show, followed by a confirmation prompt — but nothing is downloaded or changed. This is the safe way to check a command whose effect is uncertain.
Installing without confirmation. The -y flag answers yes to the confirmation prompt, which is useful in scripts where there is no user to confirm.
sudo apt install -y nginx
The flag should be used with care, because it removes the safety check that the plan provides. In a script, the plan is not seen by anyone, so the confirmation is meaningless. In an interactive session, the flag should not be the default.
Why the plan should be read. The plan shows which packages will be installed, upgraded, or removed. If the plan includes a removal that was not expected, the command should be aborted. The removals are the dangerous part — an install that removes a package the system depends on can break the system.
Why --no-install-recommends is sometimes used. Debian packages have two dependency types: Depends (required) and Recommends (suggested). By default, apt installs recommends, which can pull in more packages than expected. The --no-install-recommends flag installs only the required dependencies, producing a smaller installation.
sudo apt install --no-install-recommends nginx
The flag is useful on servers and in containers where disk space matters and the suggested packages are not needed.
Why the default installs recommends. The recommends are packages that the maintainer considers useful in most cases — documentation, common plugins, complementary tools. Installing them by default produces a more complete installation, at the cost of more disk space. The default is right for a desktop; the flag is right for a minimal server.
Installing a local package file
A .deb file downloaded from a website or built from source is installed with apt install ./file.deb, not with dpkg -i.
sudo apt install ./package.deb
The apt command reads the local file, resolves its dependencies from the repositories, and installs both the package and its dependencies in one transaction. The ./ prefix tells apt that the argument is a file path rather than a package name.
Why dpkg -i is not the right tool. dpkg is the low-level installer. It installs the package file but does not resolve dependencies and does not consult the repositories. If the package has dependencies that are not installed, dpkg -i installs the package anyway, leaving it in a “broken” state — installed but not configured, because its dependencies are missing. The high-level tool is the one that resolves dependencies, and apt install ./file.deb uses it.
Why dpkg -i is still used. dpkg is useful for inspecting a package without installing it (dpkg -c file.deb lists its contents), for extracting it without installing (dpkg -x file.deb dir), and for the rare case where a package must be installed without dependency resolution. But for ordinary installation, the high-level tool is correct.
Why the ./ prefix is required. Without the ./, apt would interpret the argument as a package name and look for it in the repositories. The ./ makes it a path, which apt treats as a local file. The distinction is easy to miss, and the error message when it is missed is unhelpful.
Why installing a local .deb is risky. A .deb from a website has not been through the distribution’s review process. It may be malicious, poorly built, or incompatible with the installed system. Installing from a repository is safer because the repository’s packages are built and tested by the distribution. A local .deb should be treated with the same caution as any downloaded executable.
The equivalent commands on other distributions
The concepts are identical, and the syntax is the difference. The four major package managers are covered here.
Fedora, RHEL, and derivatives use dnf.
sudo dnf install nginx
sudo dnf install nginx curl git
sudo dnf install ./package.rpm
sudo dnf install nginx-1.24.0
dnf resolves dependencies, verifies signatures, and installs in one transaction. The ./ prefix works for local .rpm files, and dnf resolves their dependencies from the repositories. The version can be specified with - or =, depending on the package.
openSUSE uses zypper.
sudo zypper install nginx
sudo zypper install nginx curl git
sudo zypper install ./package.rpm
zypper uses install as the subcommand and accepts multiple packages. The --no-recommends flag is the equivalent of apt --no-install-recommends.
Arch uses pacman.
sudo pacman -S nginx
sudo pacman -S nginx curl git
sudo pacman -U ./package.pkg.tar.zst
The -S flag means “sync and install” — it syncs the package database and installs the package. The -U flag installs a local package file. Arch does not separate the high-level and low-level tools, so pacman does both.
Why the syntax differs but the behavior is the same. Each tool has its own command vocabulary, shaped by its history and its design philosophy. apt uses subcommands (install, remove, update), dnf uses subcommands (install, remove, upgrade), zypper uses subcommands (install, remove, update), and pacman uses single-letter flags (-S, -R, -Syu). The differences are surface-level; the operations are the same.
Why a local package file needs the high-level tool. On every distribution, installing a local package file directly with the low-level tool (rpm -i) skips dependency resolution. The high-level tool — dnf install ./file.rpm, zypper install ./file.rpm, apt install ./file.deb — resolves dependencies and installs the complete set. The pattern is universal.
| Operation | apt | dnf | zypper | pacman |
|---|---|---|---|---|
| Install | apt install | dnf install | zypper install | pacman -S |
| Install local | apt install ./f.deb | dnf install ./f.rpm | zypper install ./f.rpm | pacman -U ./f |
| No recommends | --no-install-recommends | --setopt=install_weak_deps=False | --no-recommends | --asexplicit (n/a) |
| Simulate | -s | --assumeno | --dry-run | --print |
| Yes | -y | -y | -y | --noconfirm |
Recovering from a failed install
An install can fail for several reasons: a network failure during download, a dependency conflict, a package that fails during configuration, or a user who interrupts the command. The package database can be left in a state that blocks further operations, and the recovery tools fix it.
The symptom. The package manager reports that a package is “half-installed” or “unconfigured,” and refuses to install or remove anything until the state is repaired.
sudo apt install nginx
# E: Unmet dependencies. Try 'apt --fix-broken install' with no packages.
The repair commands. apt --fix-broken install (or apt install -f) attempts to resolve the broken dependency state by installing the missing dependencies or removing the broken package. dpkg --configure -a completes the configuration of any packages that were unpacked but not configured.
sudo apt --fix-broken install
sudo dpkg --configure -a
The first command resolves dependency problems. The second completes configuration of packages that were left in the unpacked state. Together they repair most broken states.
Why the repair is necessary. The package database records the state of each package: installed, unpacked, configured, half-configured. Operations check these states, and a package in an inconsistent state blocks operations on packages that depend on it. The repair tools bring the states back to a consistent value.
Why a failed install can happen mid-transaction. If the power fails or the process is killed during an install, the package may be unpacked but not configured. The database records this, and the repair completes the configuration. The design anticipates interruption and provides a way to recover.
Why the recovery should be done before other operations. Installing or removing other packages while the database is in a broken state can compound the problem. The repair should be the first thing done, before any other package operation.
Why the recovery tools are safe to run. They do not make arbitrary changes. They resolve dependencies and complete configuration for packages that are already in the database. Running them when the database is healthy is a no-op. The risk is low, and they should be the first response to a package manager that refuses to operate.
Complete Example Session
# ============================================
# PART 1: REFRESH AND INSTALL
# ============================================
sudo apt update
# Reading package lists... Done
sudo apt install nginx
# Reading package lists... Done
# Building dependency tree... Done
# The following additional packages will be installed:
# nginx-common nginx-core
# The following NEW packages will be installed:
# nginx nginx-common nginx-core
# 0 upgraded, 3 newly installed, 0 to remove.
# Need to get 1,234 kB of archives.
# After this operation, 5,678 kB of additional disk space will be used.
# Do you want to continue? [Y/n] y
# ...
# Setting up nginx (1.24.0-1ubuntu1) ...
# ============================================
# PART 2: INSTALL MULTIPLE
# ============================================
sudo apt install nginx curl git
# Installs all three in one transaction
# ============================================
# PART 3: SPECIFIC VERSION
# ============================================
apt policy nginx
# nginx:
# Installed: 1.24.0-1ubuntu1
# Candidate: 1.24.0-1ubuntu1
# Version table:
# *** 1.24.0-1ubuntu1 500
# 500 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages
# 100 /var/lib/dpkg/status
sudo apt install nginx=1.24.0-1ubuntu1
# ============================================
# PART 4: SIMULATE
# ============================================
apt install -s nginx
# Shows the plan without applying it
# ============================================
# PART 5: NO RECOMMENDS
# ============================================
sudo apt install --no-install-recommends nginx
# ============================================
# PART 6: INSTALL LOCAL .DEB
# ============================================
# Download a .deb file
wget https://example.com/package.deb
# Install with apt (resolves dependencies)
sudo apt install ./package.deb
# ============================================
# PART 7: INSPECT BEFORE INSTALLING
# ============================================
# List the contents of a .deb
dpkg -c package.deb | head
# Show the package info
dpkg -I package.deb
# Extract without installing
dpkg -x package.deb /tmp/extracted
# ============================================
# PART 8: REPAIR A BROKEN STATE
# ============================================
sudo apt install some-package
# E: Unmet dependencies. Try 'apt --fix-broken install'.
sudo apt --fix-broken install
# Resolves the dependency problem
sudo dpkg --configure -a
# Completes configuration of unpacked packages
# ============================================
# PART 9: THE SAME ON FEDORA
# ============================================
sudo dnf install nginx
sudo dnf install nginx curl git
sudo dnf install ./package.rpm
sudo dnf install nginx-1.24.0
# ============================================
# PART 10: THE SAME ON ARCH
# ============================================
sudo pacman -S nginx
sudo pacman -S nginx curl git
sudo pacman -U ./package.pkg.tar.zst
# ============================================
# PART 11: WHAT NOT TO DO
# ============================================
# Don't use dpkg -i for a .deb with dependencies
# sudo dpkg -i package.deb # leaves unmet dependencies
# Don't skip apt update
# apt install nginx # may fail if the index is stale
# Don't use -y without reading the plan
# The plan may include removals you did not expect
# Don't install from an untrusted .deb
# The package runs arbitrary scripts during install
# Don't run other package operations on a broken database
# Repair first with --fix-broken
The eleven parts cover the install command, multiple packages, specific versions, simulation, recommends, local files, inspection, repair, and the equivalents on Fedora and Arch.
Quick Reference
The Install Command
| Distribution | Command |
|---|---|
| Debian/Ubuntu | sudo apt install package |
| Fedora/RHEL | sudo dnf install package |
| openSUSE | sudo zypper install package |
| Arch | sudo pacman -S package |
Common Flags
| Flag | Purpose |
|---|---|
-y | Answer yes to prompts |
-s | Simulate (apt) |
--dry-run | Simulate (zypper) |
--print | Simulate (pacman) |
--no-install-recommends | Skip recommended deps |
-V | Show versions in the plan |
--reinstall | Reinstall an installed package |
Installing Local Files
| Distribution | Command |
|---|---|
| Debian | sudo apt install ./file.deb |
| Fedora | sudo dnf install ./file.rpm |
| openSUSE | sudo zypper install ./file.rpm |
| Arch | sudo pacman -U ./file.pkg.tar.zst |
Inspecting a Package
| Command | Purpose |
|---|---|
dpkg -c file.deb | List contents |
dpkg -I file.deb | Show metadata |
dpkg -x file.deb dir | Extract to dir |
rpm -qlp file.rpm | List contents |
rpm -qip file.rpm | Show metadata |
Repair Commands
| Command | Purpose |
|---|---|
apt --fix-broken install | Resolve unmet dependencies |
dpkg --configure -a | Complete configuration |
apt install -f | Same as fix-broken |
dnf check | Check for problems (Fedora) |
Version Queries
| Command | Purpose |
|---|---|
apt policy pkg | Show available versions |
apt-cache madison pkg | Show versions |
dnf list pkg --showduplicates | Show versions |
pacman -Si pkg | Show repo versions |
Best Practices
✅ Do This:
# Update the index before installing
sudo apt update && sudo apt install nginx # ✅
# Install related packages together
sudo apt install nginx curl git # ✅
# Simulate a command whose effect is uncertain
apt install -s nginx # ✅
# Use apt for local .deb files
sudo apt install ./package.deb # ✅
# Inspect a package before installing
dpkg -I package.deb && dpkg -c package.deb # ✅
# Read the plan before confirming
# The plan shows installs, upgrades, and removals # ✅
# Repair a broken state before other operations
sudo apt --fix-broken install && sudo dpkg --configure -a # ✅
# Use --no-install-recommends on servers
sudo apt install --no-install-recommends nginx # ✅
❌ Don’t Do This:
# Don't use dpkg -i for packages with dependencies
sudo dpkg -i package.deb # leaves unmet dependencies # ⚠️
# Don't skip apt update
sudo apt install nginx # may fail with stale index # ⚠️
# Don't use -y without reviewing the plan
sudo apt install -y some-package # removes packages silently # ⚠️
# Don't install from untrusted sources
sudo apt install ./downloaded-from-random-site.deb # ⚠️
# Don't run package operations on a broken database
sudo apt install other-package # compounds the problem # ⚠️
# Don't specify versions without checking availability
sudo apt install nginx=9.99 # version not in repository # ⚠️
# Don't mix package managers for the same software
# Installing a snap over a native package causes conflicts # ⚠️
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
Forgot apt update | Package not found | Run update first |
dpkg -i used directly | Unmet dependencies | Use apt install ./f.deb |
./ prefix omitted | Treated as package name | Add ./ for local files |
| Unread plan | Unexpected removal | Read before confirming |
-y in interactive use | No safety check | Use only in scripts |
| Broken state ignored | Further operations fail | Run --fix-broken |
Untrusted .deb | Malicious scripts run | Verify the source |
| Wrong version requested | Package not found | Check apt policy |
Real-World Examples
1. Install a web server
sudo apt update && sudo apt install nginx
2. Install development tools
sudo apt install build-essential git curl
3. Install a specific version
sudo apt install nginx=1.24.0-1ubuntu1
4. Simulate first
apt install -s nginx
5. Install a local .deb
sudo apt install ./google-chrome-stable_current_amd64.deb
6. Inspect a package
dpkg -I package.deb && dpkg -c package.deb
7. Minimal server install
sudo apt install --no-install-recommends nginx
8. Repair broken dependencies
sudo apt --fix-broken install
9. Complete pending configuration
sudo dpkg --configure -a
10. Fedora install
sudo dnf install nginx
Visual: The Install Flow
┌──────────────────────────────────────────────────────────┐
│ sudo apt install nginx │
│ │ │
│ ▼ │
│ 1. Read local package index │
│ │ │
│ ▼ │
│ 2. Locate nginx and read its dependencies │
│ │ │
│ ▼ │
│ 3. Check which dependencies are missing │
│ │ │
│ ▼ │
│ 4. Build the dependency graph │
│ │ │
│ ▼ │
│ 5. Present the plan │
│ │ │
│ ├── user aborts ──► nothing happens │
│ │ │
│ └── user confirms │
│ │ │
│ ▼ │
│ 6. Download packages │
│ │ │
│ ▼ │
│ 7. Verify checksums and signatures │
│ │ │
│ ▼ │
│ 8. Hand to dpkg for installation │
│ │ │
│ ▼ │
│ 9. Run pre/post scripts, place files │
│ │ │
│ ▼ │
│ 10. Record in the database │
│ │
└──────────────────────────────────────────────────────────┘
Visual: apt vs dpkg for Local Files
┌──────────────────────────────────────────────────────────┐
│ dpkg -i package.deb │
│ │
│ - Installs the package file │
│ - Does NOT consult repositories │
│ - Does NOT resolve dependencies │
│ - Leaves unmet dependencies │
│ │
│ Result: package installed but unconfigured. │
│ │
├──────────────────────────────────────────────────────────┤
│ apt install ./package.deb │
│ │
│ - Reads the local file │
│ - Consults repositories for dependencies │
│ - Resolves and installs the full set │
│ - Configures everything │
│ │
│ Result: package installed and configured. │
│ │
│ The ./ prefix tells apt it is a file, not a name. │
│ │
└──────────────────────────────────────────────────────────┘
Visual: Dependency Types
┌──────────────────────────────────────────────────────────┐
│ Depends │
│ Required. The package does not work without it. │
│ Always installed. │
│ │
│ Recommends │
│ Suggested. The package works but is less complete. │
│ Installed by default, skipped with │
│ --no-install-recommends. │
│ │
│ Suggests │
│ Optional. Related but independent. │
│ Not installed by default. │
│ │
│ Conflicts │
│ Cannot coexist. The resolver removes one. │
│ │
│ Replaces / Breaks │
│ The package supersedes another. │
│ │
└──────────────────────────────────────────────────────────┘
Visual: Broken State Recovery
┌──────────────────────────────────────────────────────────┐
│ Install interrupted or dependency missing │
│ │ │
│ ▼ │
│ Package in "unpacked" or "half-configured" state │
│ │ │
│ ▼ │
│ apt refuses further operations │
│ E: Unmet dependencies │
│ │ │
│ ▼ │
│ sudo apt --fix-broken install │
│ │ │
│ └── resolves dependencies: │
│ installs missing, removes broken │
│ │ │
│ ▼ │
│ sudo dpkg --configure -a │
│ │ │
│ └── completes configuration of unpacked packages │
│ │ │
│ ▼ │
│ Database is consistent │
│ Normal operations resume │
│ │
└──────────────────────────────────────────────────────────┘
Visual: Command Mapping
┌──────────────────────────────────────────────────────────┐
│ INSTALL apt install dnf install │
│ zypper install pacman -S │
│ │
│ LOCAL FILE apt install ./f.deb │
│ dnf install ./f.rpm │
│ zypper install ./f.rpm │
│ pacman -U ./f.pkg.tar.zst │
│ │
│ NO RECOMMENDS apt --no-install-recommends │
│ zypper --no-recommends │
│ dnf --setopt=install_weak_deps=False│
│ │
│ SIMULATE apt -s dnf --assumeno │
│ zypper --dry-run │
│ pacman --print │
│ │
│ REPAIR apt --fix-broken install │
│ dpkg --configure -a │
│ dnf check │
│ │
└──────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Debian install | sudo apt install package |
| Fedora install | sudo dnf install package |
| openSUSE install | sudo zypper install package |
| Arch install | sudo pacman -S package |
| Local Debian file | sudo apt install ./file.deb |
| Local RPM file | sudo dnf install ./file.rpm |
| Local Arch file | sudo pacman -U ./file.pkg.tar.zst |
| Simulate | -s, --dry-run, --print |
| Minimal install | --no-install-recommends |
| Repair | apt --fix-broken install |
| Complete config | dpkg --configure -a |
Key takeaways:
apt installdownloads, resolves, and installs in one transaction — the plan is shown before the change is applied, and the user confirmsapt updatemust run beforeapt install— the local package index is a snapshot, and a stale index produces failures and wrong plansapt install ./file.debis the correct way to install a local package — it resolves dependencies from the repositories, whichdpkg -idoes not- The
./prefix tellsaptthe argument is a path, not a package name — omitting it makesaptsearch the repositories and fail --no-install-recommendsinstalls only the required dependencies — the right choice on servers and in containers where disk space matters-ssimulates the install — the plan is shown, nothing is downloaded, and the command is the safe way to check an uncertain operation- A failed install leaves a broken state —
apt --fix-broken installanddpkg --configure -arepair it, and they should be run before any other package operation - The concepts are universal —
dnf install,zypper install, andpacman -Sdo the same thing with different syntax - Local package files are risky — they have not been through the distribution’s review, and they run arbitrary scripts during installation
- The plan should always be read — it shows which packages will be installed, upgraded, and, most importantly, removed
Remember: Installing a package is a transaction with a plan, a resolution step, a download, and a configuration. The high-level tool does the work; the low-level tool does the installation. Local files require the high-level tool for dependency resolution, and a broken state requires the repair tools before anything else. The command is short, but understanding what it does is what makes the failures diagnosable and the recovery straightforward.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!