
Table of Contents
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.
sudo apt update, then run sudo apt install <package-name>. For automated scripts or CI pipelines, always append -y to skip prompts and use DEBIAN_FRONTEND=noninteractive to prevent interactive dialogs from hanging your deployment process.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
- Update the package index: Always run
sudo apt updatebefore any installation. This downloads the latestPackages.gzfiles from all configured repositories. - 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. - 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. - 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.
| Feature | apt | apt-get |
|---|---|---|
| Primary Use Case | Interactive terminal sessions | Scripts and automation |
| Output Format | Human-readable with progress bars | Stable, parseable text output |
| Backward Compatibility | Not guaranteed across releases | Stable CLI interface since 2000s |
| Search Functionality | Built-in apt search | Requires separate apt-cache |
| Script Safety | May change output format | Safe 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-yesas 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 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
- Check held packages:
apt-mark showholdreveals manually pinned packages blocking upgrades. - Identify broken state:
sudo dpkg --auditlists packages in inconsistent states. - Fix interrupted installs:
sudo dpkg --configure -acompletes pending configurations. - Resolve missing deps:
sudo apt install -fattempts automatic repair. - Review logs: Check
/var/log/apt/history.logand/var/log/dpkg.logfor 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=yesexcept 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.
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.