Install Packages with apt on Ubuntu

Khimananda Oli 7 min read Virtualization
Install Packages with apt on Ubuntu

By Khimananda Oli | Last reviewed: August 2026

When you need to deploy software reliably on Debian-based systems, knowing how to install packages with apt on Ubuntu is a fundamental skill that separates stable production environments from fragile ones. While the basic syntax seems simple, improper usage leads to broken dependencies, unattended upgrade failures, and security vulnerabilities in both local development and cloud infrastructure. This guide covers the exact workflows, safety flags, and automation patterns I use daily as a DevOps engineer to manage fleets of Ubuntu servers securely.

User Commandapt install pkgLocal Cache/var/lib/apt/listsDependency SolverAPT Algorithmdpkg EngineUnpack & ConfigureRemote Mirrors
The internal flow when you install packages with apt on Ubuntu: user input triggers cache lookup, dependency solving, and final dpkg execution.

How do you correctly install packages with apt on Ubuntu?

The most common mistake engineers make is running apt install without first synchronizing the local package index. APT does not query the internet in real-time during installation; it relies entirely on a cached metadata database stored in /var/lib/apt/lists/. If this cache is stale, you risk installing outdated versions with known CVEs or encountering "unable to locate package" errors for newly released software.

The standard safe installation sequence

  1. Update the package index: Always run sudo apt update before any installation. This downloads the latest Packages.gz files from all configured repositories.
  2. Verify the candidate version: Use apt policy <package-name> to confirm which version will be installed and from which repository. This prevents accidental installs from untrusted PPAs.
  3. Install with simulation first: Run sudo apt install --dry-run <package-name> to preview changes without modifying the system. Review the list of additional packages to be installed or removed.
  4. Execute the installation: Run sudo apt install <package-name> once you are satisfied with the planned changes.
# Safe installation workflow for production
sudo apt update
apt policy nginx
sudo apt install --dry-run nginx
sudo apt install nginx

This disciplined approach mirrors the verification steps we apply in initial Ubuntu server setup to ensure baseline integrity before adding application workloads.

What is the difference between apt and apt-get?

You will see both commands in documentation and legacy scripts. Understanding the distinction prevents confusion when reading older tutorials or writing automation.

Featureaptapt-get
Primary Use CaseInteractive terminal sessionsScripts and automation
Output FormatHuman-readable with progress barsStable, parseable text output
Backward CompatibilityNot guaranteed across releasesStable CLI interface since 2000s
Search FunctionalityBuilt-in apt searchRequires separate apt-cache
Script SafetyMay change output formatSafe for parsing in CI/CD

In practice, use apt when you are logged into a server interactively. Use apt-get in Dockerfiles, Ansible playbooks, GitHub Actions, and shell scripts. The underlying library (libapt) is identical; only the frontend interface differs. Never parse apt output programmatically — its formatting can change between Ubuntu releases without notice, breaking your automation silently.

How do you automate apt installs in CI/CD and scripts?

Non-interactive installation is critical for reproducible infrastructure. Interactive prompts for configuration files or timezone data will hang your pipeline indefinitely. When you provision servers automatically, these flags are mandatory.

Essential environment variables and flags

  • DEBIAN_FRONTEND=noninteractive: Prevents debconf from spawning interactive dialogs. Set this as an environment variable, not just a command prefix.
  • -y / --assume-yes: Automatically answers "yes" to all prompts. Never use --force-yes as it bypasses essential safety checks.
  • -o Dpkg::Options::="--force-confold": Keeps existing configuration files if modified locally, preventing unexpected overwrites during upgrades.
  • --no-install-recommends: Skips recommended packages, reducing image size and attack surface in containers.
# Production-grade non-interactive install
export DEBIAN_FRONTEND=noninteractive
apt-get update && apt-get install -y \
  --no-install-recommends \
  -o Dpkg::Options::="--force-confold" \
  curl ca-certificates gnupg
❌ Interactive Mode (Breaks CI)apt install tzdataHANGS: Waiting for input✅ Non-Interactive (CI Safe)DEBIAN_FRONTEND=noninteractive apt-get install -y tzdataCompletes in secondsKey Environment VariablesDEBIAN_FRONTEND=noninteractiveDisables all UI prompts-y FlagAuto-confirm promptsNever use --force-yes--force-confoldKeep existing configsPrevents overwrite surprises
Why non-interactive mode matters when you install packages with apt on Ubuntu in automated environments versus manual terminal sessions.

How do you troubleshoot broken apt dependencies?

Dependency hell occurs when partial upgrades fail, PPAs conflict with official repos, or disk space runs out mid-installation. Before reaching for nuclear options like apt purge, follow this diagnostic sequence.

Diagnostic commands in order

  1. Check held packages: apt-mark showhold reveals manually pinned packages blocking upgrades.
  2. Identify broken state: sudo dpkg --audit lists packages in inconsistent states.
  3. Fix interrupted installs: sudo dpkg --configure -a completes pending configurations.
  4. Resolve missing deps: sudo apt install -f attempts automatic repair.
  5. Review logs: Check /var/log/apt/history.log and /var/log/dpkg.log for exact failure timestamps.
# Recovery sequence for broken apt state
sudo dpkg --configure -a
sudo apt install -f
sudo apt update
sudo apt upgrade

If apt install -f fails repeatedly, identify the specific conflicting package with apt-rdepends --reverse <broken-package> and remove only that blocker rather than forcing system-wide repairs. In regulated environments following DevSecOps principles, document every manual intervention for audit trails.

How do you secure apt repositories and verify package integrity?

Supply chain attacks increasingly target package managers. Unsigned repositories, HTTP mirrors, and wildcard GPG keys are unacceptable in production. Every repository must be cryptographically verified.

Modern repository security checklist

  • HTTPS only: Reject any repository using plain HTTP. Transport encryption prevents MITM tampering even before signature verification.
  • Signed-by field: Modern sources.list entries should specify [signed-by=/usr/share/keyrings/repo.gpg] instead of global trusted keys.
  • No wildcard trust: Avoid trusted=yes except in isolated air-gapped build environments with explicit justification.
  • Pin priorities: Use /etc/apt/preferences.d/ to control which repository wins when multiple sources offer the same package.
# Secure third-party repository format (Ubuntu 22.04+)
deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/ubuntu jammy stable

Always download GPG keys via HTTPS directly from the vendor's official site, never from keyserver networks where poisoning is trivial. Store keys in /usr/share/keyrings/ with restrictive permissions (644) rather than the deprecated /etc/apt/trusted.gpg.d/ directory.

Vendor ServerPackages + ReleaseGPG Signed MetadataHTTPSLocal APT Cache/var/lib/apt/listsVerified Signaturesdpkg InstallChecksum ValidationFile Integrity Check⚠ Insecure PatternHTTP TransportGlobal Trusted KeysNo signed-by Field✓ Secure PatternHTTPS OnlyPer-Repo GPG KeysExplicit signed-by
Secure versus insecure repository configurations when you install packages with apt on Ubuntu in production environments.

Mastering Package Installation for Reliable Infrastructure

Knowing how to install packages with apt on Ubuntu correctly is foundational to operating secure, reproducible Linux infrastructure at scale. The difference between fragile and resilient systems lies in disciplined habits: always updating indexes before installs, using non-interactive flags in automation, verifying repository signatures, and diagnosing breakage methodically rather than destructively. These practices compound over time, reducing incident frequency and audit friction significantly. If your team needs help establishing hardened baseline configurations or automating compliant server provisioning, reach out to discuss your infrastructure requirements.

Frequently Asked Questions

Run sudo apt update to refresh metadata, then execute sudo apt install package-name. Confirm the prompt to download and configure dependencies automatically from configured repositories.

Apt provides a user-friendly interface with progress bars and color output for interactive use. Apt-get remains preferred for shell scripts and automation due to stable, predictable output formatting across Ubuntu versions.

Use apt search keyword to find packages by name or description. For exact matches, try apt show package-name to view metadata before installation without modifying system state.

Broken dependencies often result from mixed repositories or interrupted installs. Run sudo apt --fix-broken install to resolve conflicts, then retry your original installation command after verifying source list integrity.

Execute sudo apt purge package-name to delete binaries and configuration files. Follow with sudo apt autoremove to clean unused dependencies left behind after removal.

Yes. Append equals sign and version number like sudo apt install nginx=1.24.0-2ubuntu3. Pin that version afterward to prevent automatic upgrades during routine maintenance cycles.

Run sudo apt update followed by sudo apt upgrade. Review the changelog when prompted. Use full-upgrade instead only if dependency changes require removing obsolete packages.

Main sources reside in /etc/apt/sources.list. Additional third-party repos live in /etc/apt/sources.list.d/ as separate files. Always verify GPG keys match before enabling new sources.

Use sudo add-apt-repository ppa:owner/name which imports signing keys automatically. Never manually edit sources without verifying key fingerprints against official documentation to avoid supply chain attacks.

It displays installed versus candidate versions plus priority levels from each repository. This helps diagnose why an unexpected version was selected during installation or upgrade operations.

Run sudo apt-mark hold package-name to prevent upgrades. Release later with unhold subcommand. Verify status anytime using apt-mark showhold to audit pinned packages.

No. Mixing releases causes dependency hell and system instability. Always match sources.list entries to your exact Ubuntu codename verified via lsb_release -cs output.

Apt checks GPG signatures automatically against trusted keyrings. If verification fails, never force install. Instead fetch updated keyrings or report compromised mirrors to maintainers immediately.

Set DEBIAN_FRONTEND=noninteractive and pass -y flag to suppress prompts. Combine with needrestart disablement in CI pipelines to avoid hanging on service restart dialogs during provisioning.

Run sudo apt autoclean to remove outdated deb files while keeping current versions. Use clean instead to wipe entire cache when reclaiming maximum disk space is necessary.