Skip to content

Apt

Chapter 28: apt - Debian/Ubuntu Package Manager Deep Dive

Section titled “Chapter 28: apt - Debian/Ubuntu Package Manager Deep Dive”

Mastering Package Management on Debian-Based Systems

Section titled “Mastering Package Management on Debian-Based Systems”

APT (Advanced Package Tool) is a powerful package management system that forms the backbone of Debian, Ubuntu, Linux Mint, and other Debian-based distributions. It provides a high-level interface to the lower-level dpkg package management system, handling dependency resolution, package searching, and automatic updates.

APT Package Management Architecture
+------------------------------------------------------------------+
| |
| User Space |
| +-------------------------------------------------------------+ |
| | apt Command | |
| | (High-level interface for end users) | |
| +-------------------------------------------------------------+ |
| | |
| v |
| +-------------------------------------------------------------+ |
| | apt-get / apt-cache | |
| | (Low-level operations, scripts, dependency resolution) | |
| +-------------------------------------------------------------+ |
| | |
| v |
| +-------------------------------------------------------------+ |
| | dpkg | |
| | (Debian package manager - handles .deb files directly) | |
| +-------------------------------------------------------------+ |
| | |
| v |
| +-------------------------------------------------------------+ |
| | /var/lib/dpkg | |
| | (Package database - installed packages info) | |
| +-------------------------------------------------------------+ |
| |
| Kernel Space |
| +-------------------------------------------------------------+ |
| | File System Operations | |
| | (/var/cache/apt/archives - downloaded packages) | |
| | (/var/lib/dpkg - package database) | |
| | (/etc - configuration files) | |
| +-------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Command Comparison
+------------------------------------------------------------------+
| |
| Command | Purpose | Use Case |
| ------------|---------------------|---------------------------|
| apt | All-in-one tool | Interactive use (recommended)|
| apt-get | Script-friendly | Automation, stable scripts |
| apt-cache | Query package cache | Search, show info |
| apt-file | Search file in pkgs | Find which package has file|
| dpkg | Direct .deb mgmt | Install local .deb files |
| |
| Modern apt (v1.3+) includes: |
| +----------------------------------------------------------+ |
| | apt list - List packages (like dpkg -l) | |
| | apt edit - Edit sources | |
| | apt clean - Clean cache | |
| | apt autoremove - Remove unused dependencies | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

The sources.list file defines where apt fetches packages. Each line follows a specific format:

sources.list Format
+------------------------------------------------------------------+
| |
| deb|deb-src [options] URI distribution [component1] [component2]|
| |
| +----------------------------------------------------------+ |
| | deb - Binary packages (compiled) | |
| | deb-src - Source packages (source code) | |
| +----------------------------------------------------------+ |
| |
| URI Options: |
| +----------------------------------------------------------+ |
| | http:// - HTTP mirror | |
| | https:// - Secure HTTP mirror | |
| | ftp:// - FTP mirror | |
| | file:// - Local repository | |
| | cdrom: - CD/DVD drive | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Ubuntu Repository Structure
+------------------------------------------------------------------+
| |
| Main Repository |
| +----------------------------------------------------------+ |
| | - Officially supported free and open-source software | |
| | - Security updates provided | |
| | - Maintained by Canonical | |
| | - Examples: coreutils, python3, nginx | |
| +----------------------------------------------------------+ |
| |
| Universe Repository |
| +----------------------------------------------------------+ |
| | - Community-maintained free and open-source software | |
| | - Limited support (best-effort) | |
| | - May not receive timely security updates | |
| | - Examples: htop, vim, git | |
| +----------------------------------------------------------+ |
| |
| Restricted Repository |
| +----------------------------------------------------------+ |
| | - Proprietary drivers (NVIDIA, Broadcom) | |
| | - Supported by Canonical | |
| +----------------------------------------------------------+ |
| |
| Multiverse Repository |
| +----------------------------------------------------------+ |
| | - Software with licensing restrictions | |
| | - Not officially supported | |
| | - Examples: codecs, some closed-source tools | |
| +----------------------------------------------------------+ |
| |
| Partner Repository |
| +----------------------------------------------------------+ |
| | - Proprietary software from Canonical's partners | |
| | - Examples: Skype, Spotify, Dropbox | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# /etc/apt/sources.list for Ubuntu 22.04 (Jammy)
# Official Main Repository
deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
# Security Updates
deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
# Pre-release (Proposed) - Testing
# deb http://archive.ubuntu.com/ubuntu/ jammy-proposed main restricted universe multiverse
# Canonical Partner Repository
deb http://archive.canonical.com/ubuntu jammy partner
# Third-party Repositories (Examples)
# Docker
deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable
# Node.js
deb https://deb.nodesource.com/node_18.x jammy main
# PostgreSQL
deb http://apt.postgresql.org/pub/repos/apt jammy-pgdg main

Package Dependencies
+------------------------------------------------------------------+
| |
| Depends (Hard Requirement) |
| +----------------------------------------------------------+ |
| | Package MUST be installed for this package to work | |
| | If dependency is missing, installation will FAIL | |
| | Example: nginx depends on libc6, libpcre3 | |
| +----------------------------------------------------------+ |
| |
| Pre-Depends (Strict Requirement) |
| +----------------------------------------------------------+ |
| | Must be FULLY installed BEFORE this package installs | |
| | Used for critical system packages | |
| | Example: base-files depends on base-passwd | |
| +----------------------------------------------------------+ |
| |
| Recommends (Suggested) |
| +----------------------------------------------------------+ |
| | Package works BETTER with this dependency | |
| | Usually installed by default | |
| | Example: firefox recommends xul-ext-gdata-provider | |
| +----------------------------------------------------------+ |
| |
| Suggests (Optional Enhancement) |
| +----------------------------------------------------------+ |
| | Complementary packages that enhance functionality | |
| | NOT installed by default | |
| | Example: vim suggests vim-doc, cscope | |
| +----------------------------------------------------------+ |
| |
| Conflicts (Incompatible) |
| +----------------------------------------------------------+ |
| | Cannot be installed together with this package | |
| | Example: systemd conflicts with sysvinit | |
| +----------------------------------------------------------+ |
| |
| Replaces (Supersedes) |
| +----------------------------------------------------------+ |
| | This package replaces files from another package | |
| | Example: openssh-client replaces ssh | |
| +----------------------------------------------------------+ |
| |
| Provides (Virtual Package) |
| +----------------------------------------------------------+ |
| | This package provides a virtual package name | |
| | Example: mail-transport-agent provides postfix | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Package States in dpkg
+------------------------------------------------------------------+
| |
| install - Package is properly installed |
| +----------------------------------------------------------+ |
| | - Files are in place | |
| | - Configuration is complete | |
| | - No known issues | |
| +----------------------------------------------------------+ |
| |
| config-files - Only config files remain |
| +----------------------------------------------------------+ |
| | - Package was removed but config kept | |
| | - Can be completely removed with 'dpkg --purge' | |
| +----------------------------------------------------------+ |
| |
| half-installed - Installation failed |
| +----------------------------------------------------------+ |
| | - Files partially installed | |
| | - Requires manual intervention | |
| +----------------------------------------------------------+ |
| |
| half-configured - Configuration failed |
| +----------------------------------------------------------+ |
| | - Package installed but configuration didn't complete | |
| | - Run 'dpkg --configure -a' to fix | |
| +----------------------------------------------------------+ |
| |
| unpacked - Files extracted but not configured |
| +----------------------------------------------------------+ |
| | - Files in place but not ready to use | |
| | - Run 'dpkg --configure package' to complete | |
| +----------------------------------------------------------+ |
| |
| triggers-awaited - Waiting for trigger processing |
| +----------------------------------------------------------+ |
| | - Package ready but waiting for another trigger | |
| | Usually resolves automatically | |
| +----------------------------------------------------------+ |
| |
| triggers-in-progress - Trigger being processed |
| +----------------------------------------------------------+ |
| | - System is processing triggers | |
| | Wait for completion | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Package Version Specifiers
+------------------------------------------------------------------+
| |
| Version Format: [epoch:]upstream_version[-debian_revision] |
| |
| Example: 1:2.18.0-2ubuntu3 |
| +----------------------------------------------------------+ |
| | epoch: 1 (usually 0 or 1 for most packages) | |
| | upstream: 2.18.0 (original software version) | |
| | debian_rev: 2ubuntu3 (Debian/Ubuntu packaging version) | |
| +----------------------------------------------------------+ |
| |
| Version Comparison: |
| +----------------------------------------------------------+ |
| | 1. Compare epoch (higher = newer) | |
| | 2. Compare upstream (using string comparison) | |
| | 3. Compare debian_revision | |
| +----------------------------------------------------------+ |
| |
| Version Constraints: |
| +----------------------------------------------------------+ |
| | << - Strictly less than | |
| | <= - Less than or equal to | |
| | = - Exactly equal to | |
| | >= - Greater than or equal to | |
| | >> - Strictly greater than | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# View available versions of a package
apt-cache policy nginx
# Example output:
# nginx:
# Installed: 1.22.0-1ubuntu1
# Candidate: 1.22.0-1ubuntu1
# Version table:
# 1.24.0-1~jammy 500
# 500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
# *** 1.22.0-1ubuntu1 500
# 500 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
# 100 /var/lib/dpkg/status
# 1.18.0-1ubuntu2 500
# 500 http://archive.ubuntu.com/ubuntu jammy/main amd64 Packages
# Install specific version
sudo apt install nginx=1.18.0-1ubuntu2
# Install from specific repository
sudo apt install nginx/jammy-updates
sudo apt install nginx/jammy
# Hold package (prevent automatic upgrades)
sudo apt-mark hold nginx
# View held packages
apt-mark showhold
# Unhold package
sudo apt-mark unhold nginx

Package pinning allows you to control which versions of packages are installed from different repositories. This is crucial for production environments where you need specific versions.

Package Pinning Mechanism
+------------------------------------------------------------------+
| |
| Pin Priority Levels: |
| +----------------------------------------------------------+ |
| | 1000 - Install this version (even from lower priority) | |
| | 990 - Install unless there's another version > 1000 | |
| | 500 - Default for repositories | |
| | 400 - Higher than default | |
| | 100 - Only for dependencies | |
| | 0 - Package is not installable | |
| +----------------------------------------------------------+ |
| |
| Pin Origins: |
| +----------------------------------------------------------+ |
| | a=release (origin) - Specific release | |
| | n=release (name) - Release name (jammy, focal) | |
| | v=release (version)- Release version | |
| | c=release (component)- main, universe, multiverse | |
| | o=origin - Origin (Ubuntu, Debian) | |
| | l=origin - Label | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# /etc/apt/preferences (or /etc/apt/preferences.d/package-name)
# Pin specific package to specific version
Package: nginx
Pin: version 1.18.*
Pin-Priority: 1000
# Pin package to Ubuntu updates (higher priority)
Package: *
Pin: release a=jammy-updates
Pin-Priority: 900
# Pin package to security updates (highest)
Package: *
Pin: release a=jammy-security
Pin-Priority: 950
# Never install from specific origin
Package: apache2
Pin: origin "archive.canonical.com"
Pin-Priority: 0
# Pin to specific repository
Package: docker-ce
Pin: origin "download.docker.com"
Pin-Priority: 900
# Examples for production servers:
# Prevent kernel upgrades (stability)
Package: linux-image-generic
Pin: version 5.15.0-*
Pin-Priority: 1000
# Lock Firefox to current version
Package: firefox
Pin: version 120.*
Pin-Priority: 1000

When to Use dpkg vs apt
+------------------------------------------------------------------+
| |
| Use apt (Recommended): |
| +----------------------------------------------------------+ |
| | - Installing packages from repositories | |
| | - Automatic dependency resolution | |
| | - Upgrading packages | |
| | - Regular package management | |
| +----------------------------------------------------------+ |
| |
| Use dpkg (Direct): |
| +----------------------------------------------------------+ |
| | - Installing locally downloaded .deb files | |
| | - Reconstructing package database | |
| | - Querying installed packages | |
| | - Manual package removal (when apt fails) | |
| | - Listing files in packages | |
| | - Finding which package owns a file | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# Install a .deb package
sudo dpkg -i package.deb
sudo dpkg --install package.deb
# Install with dependencies (recommended)
sudo dpkg -i package.deb
sudo apt-get install -f # Fix missing dependencies
# Remove package (keep configuration)
sudo dpkg -r package_name
sudo dpkg --remove package_name
# Remove package AND configuration
sudo dpkg -P package_name
sudo dpkg --purge package_name
# List all installed packages
dpkg -l
dpkg -l | grep nginx # Filter specific package
# List files in a package
dpkg -L nginx
# Output:
# /.
# /usr/
# /usr/sbin/
# /usr/sbin/nginx
# /etc/
# /etc/nginx/
# /etc/nginx/nginx.conf
# ...
# Find which package owns a file
dpkg -S /etc/nginx/nginx.conf
# Output: nginx: /etc/nginx/nginx.conf
# Get package information
dpkg -s nginx
dpkg --status nginx
# Reconfigure package (run post-install scripts)
sudo dpkg-reconfigure locales
sudo dpkg-reconfigure keyboard-configuration
# List available packages
dpkg -l | head
# Check if package is installed
dpkg -l | grep "^ii" | grep nginx
# or
dpkg -s nginx >/dev/null 2>&1 && echo "Installed" || echo "Not installed"
# Emergency: Rebuild package database
sudo dpkg --configure -a
# Emergency: Remove partially installed package
sudo dpkg --remove --force-remove-reinstreq package_name

Terminal window
# Basic search
apt-cache search nginx
apt-cache search "web server"
# Search with regex
apt-cache search "^nginx"
# Search by description
apt-cache search --full "nginx"
# Show package details
apt-cache show nginx
# Show package with all fields
apt-cache showpkg nginx
# Show package dependencies
apt-cache depends nginx
# Output:
# nginx
# Depends: libc6
# Depends: libpcre3
# Depends: libssl3
# Depends: zlib1g
# Recommends: nginx-extras
# Suggests::
# Conflicts: nginx
# Replaces: nginx
# Show reverse dependencies (what depends on this)
apt-cache rdepends nginx
# Check if package is installed
apt-cache policy nginx
# Shows: Installed version, Candidate version, Package sources
# Show what a package provides (virtual packages)
apt-cache show virtualbox | grep Provides
# Find package by file
apt-file search /usr/sbin/nginx
# Update apt-file database
sudo apt-file update
# Statistics about package cache
apt-cache stats
# Unmet dependencies
apt-cache unmet
# Broken packages
apt-cache check

Package Troubleshooting Guide
+------------------------------------------------------------------+
| |
| Problem: Package in inconsistent state |
| +----------------------------------------------------------+ |
| | Symptom: "dpkg was interrupted" error | |
| | Fix: sudo dpkg --configure -a | |
| +----------------------------------------------------------+ |
| |
| Problem: Missing dependencies |
| +----------------------------------------------------------+ |
| | Symptom: "Unmet dependencies" during install | |
| | Fix: sudo apt-get install -f | |
| +----------------------------------------------------------+ |
| |
| Problem: Held broken packages |
| +----------------------------------------------------------+ |
| | Symptom: Package held back despite upgrades | |
| | Fix: sudo apt-get dist-upgrade | |
| +----------------------------------------------------------+ |
| |
| Problem: GPG key errors |
| +----------------------------------------------------------+ |
| | Symptom: "GPG error: NO_PUBKEY" | |
| | Fix: sudo apt-key adv --keyserver keyserver.ubuntu.com | |
| | --recv-keys KEYID | |
| +----------------------------------------------------------+ |
| |
| Problem: Lock files preventing installation |
| +----------------------------------------------------------+ |
| | Symptom: "Unable to acquire the dpkg lock" | |
| | Fix: Wait for other apt/dpkg to finish, or: | |
| | sudo rm /var/lib/dpkg/lock | |
| | sudo rm /var/lib/dpkg/lock-frontend | |
| | sudo rm /var/lib/apt/lists/lock | |
| | sudo dpkg --configure -a | |
| +----------------------------------------------------------+ |
| |
| Problem: Disk space issues |
| +----------------------------------------------------------+ |
| | Symptom: "No space left on device" | |
| | Fix: sudo apt-get clean | |
| | sudo apt-get autoremove | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# 1. Clean apt cache
sudo apt-get clean
sudo apt-get autoclean
sudo apt-get autoremove
# 2. Fix broken dependencies
sudo apt-get -f install
sudo dpkg --configure -a
# 3. Reinstall broken package
sudo apt-get reinstall package_name
# 4. Remove package completely
sudo apt-get remove --purge package_name
sudo apt-get autoremove --purge
# 5. Update package lists
sudo apt-get update --fix-missing
# 6. For locked dpkg (use with caution!)
sudo rm /var/lib/dpkg/lock
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/apt/lists/lock
sudo rm /var/cache/apt/archives/lock
sudo dpkg --configure -a
# 7. Check disk space
df -h
du -sh /var/cache/apt/archives
# 8. Emergency: Remove package without dependencies check
sudo dpkg --remove --force-remove-reinstreq package_name
# 9. Emergency: Force install (use carefully!)
sudo dpkg --force-all -i problem-package.deb

apt Configuration Hierarchy
+------------------------------------------------------------------+
| |
| /etc/apt/apt.conf |
| +----------------------------------------------------------+ |
| | Main configuration file (deprecated in favor of .conf) | |
| +----------------------------------------------------------+ |
| |
| /etc/apt/apt.conf.d/* |
| +----------------------------------------------------------+ |
| | Modular configuration files | |
| | Applied in alphabetical order | |
| | Example: 00aptconfig, 10preferances | |
| +----------------------------------------------------------+ |
| |
| /etc/apt/sources.list |
| +----------------------------------------------------------+ |
| | Repository sources | |
| +----------------------------------------------------------+ |
| |
| /etc/apt/sources.list.d/ |
| +----------------------------------------------------------+ |
| | Additional source files | |
| | Can add separate repo configs here | |
| +----------------------------------------------------------+ |
| |
| /etc/apt/preferences |
| +----------------------------------------------------------+ |
| | Package pinning (deprecated - use .d/ files) | |
| +----------------------------------------------------------+ |
| |
| /etc/apt/preferences.d/ |
| +----------------------------------------------------------+ |
| | Package pinning files | |
| +----------------------------------------------------------+ |
| |
| ~/.aptrc |
| +----------------------------------------------------------+ |
| | User-specific configuration | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
/etc/apt/apt.conf.d/99personal
# Download settings
APT::Get::Fix-Missing "true";
APT::Get::AutomaticRemove "true";
APT::Get::AllowUnauthenticated "false";
# Install recommended packages automatically
APT::Get::Install-Recommends "true";
# Install suggested packages
APT::Get::Install-Suggests "false";
# Remove automatically when removing required packages
APT::Get::AutomaticRemove "true";
# Download settings
Acquire::http::Proxy "http://proxy.example.com:8080";
Acquire::https::Proxy "https://proxy.example.com:8080";
# Download retries
Acquire::Retries "3";
# Parallel downloads
Acquire::http::Pipeline-Depth "5";
APT::Acquire::Max-Future-Time "86400";
# dpkg options
DPkg::Options {
"--force-confdef";
"--force-confold";
"--force-confmiss";
};
# Force yes to prompts
APT::Get::Assume-Yes "false";
APT::Get::AutomaticYes "false";
# Update options
APT::Get::Update::SourceListWarnings::NonFreeFirmware "false";
# Logging
APT::Log::File "1";
APT::Log::Date::Format "%Y-%m-%d %H:%M:%S";

GPG Key Management
+------------------------------------------------------------------+
| |
| Old Method (Debian < 12, Ubuntu < 22.04): |
| +----------------------------------------------------------+ |
| | Keys stored in /etc/apt/trusted.gpg | |
| | apt-key add <key> | |
| | PROBLEM: All keys trusted globally | |
| +----------------------------------------------------------+ |
| |
| New Method (Debian 12+, Ubuntu 22.04+): |
| +----------------------------------------------------------+ |
| | Keys stored in /usr/share/keyrings/ or | |
| | /etc/apt/keyrings/ | |
| | Signed-by in sources.list | |
| | BENEFIT: Granular trust control | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# Method 1: Using signed-by with manual key download
# Download GPG key
wget -qO - https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg > /dev/null
# Add repository with signed-by
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu jammy nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# Method 2: Using gpg to import to keyring
sudo gpg --keyserver keyserver.ubuntu.com --recv-keys KEYID
sudo gpg --export KEYID | sudo tee /etc/apt/trusted.gpg.d/mypackage.gpg > /dev/null
# Verify keys
apt-key list
# Remove old key (if migrated)
sudo apt-key del OLD_KEY_ID
Terminal window
# Verify package authenticity
apt-get install apt-transport-https
# Check package signatures
dpkg-sig --verify package.deb
# Verify repository
apt-get update 2>&1 | grep -E "(W:|E:)"
# Check for authentication issues
sudo apt-get update 2>&1 | grep "NO_PUBKEY"
# Audit installed packages
debsums -e # Check essential packages
debsums -a # Check all packages

#!/bin/bash
# production-update.sh - Production server update script
set -euo pipefail
echo "=== Production Server Package Update ==="
echo "Started at: $(date)"
# 1. Check disk space
DISK_USAGE=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 80 ]; then
echo "ERROR: Disk usage is ${DISK_USAGE}%, above 80% threshold"
exit 1
fi
# 2. Update package lists
echo "Updating package lists..."
sudo apt-get update -qq
# 3. Check for held packages
HELD=$(apt-mark showhold || true)
if [ -n "$HELD" ]; then
echo "WARNING: Held packages found:"
echo "$HELD"
fi
# 4. Check for upgrades
UPGRADES=$(apt-get -s upgrade | grep -c "^Inst " || true)
echo "Packages available for upgrade: $UPGRADES"
if [ "$UPGRADES" -eq 0 ]; then
echo "No packages to upgrade"
exit 0
fi
# 5. Show upgrade details
echo "Packages to upgrade:"
apt-get -s upgrade | grep "^Inst " | awk '{print $2, $3}'
# 6. Dry run (simulation)
echo "Running simulation..."
sudo apt-get upgrade --simulate
# 7. Perform upgrade (non-interactive)
echo "Performing upgrade..."
sudo DEBIAN_FRONTEND=noninteractive apt-get \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
upgrade -y
# 8. Remove unused packages
sudo apt-get autoremove -y
# 9. Clean cache
sudo apt-get clean
# 10. Check for reboots needed
if [ -f /var/run/reboot-required ]; then
echo "WARNING: Reboot required"
echo "Reason: $(cat /var/run/reboot-required.pkgs || echo 'Unknown')"
fi
echo "=== Update completed at: $(date) ==="
#!/bin/bash
# lock-packages.sh - Lock specific package versions
# Usage: ./lock-packages.sh nginx:1.18 postgresql:14
LOCKFILE="/etc/apt/preferences.d/pinned-versions"
echo "Package Pin Lock File" > "$LOCKFILE"
echo "" >> "$LOCKFILE"
for arg in "$@"; do
PACKAGE="${arg%%:*}"
VERSION="${arg##*:}"
echo "Package: $PACKAGE" >> "$LOCKFILE"
echo "Pin: version $VERSION" >> "$LOCKFILE"
echo "Pin-Priority: 1000" >> "$LOCKFILE"
echo "" >> "$LOCKFILE"
echo "Locked $PACKAGE to version $VERSION"
done
echo "Pinning configuration created at $LOCKFILE"
echo "Run 'sudo apt update' to apply"

Important

  1. apt vs apt-get: Use apt for interactive use, apt-get in scripts for stability
  2. sources.list format: Remember deb vs deb-src (binary vs source)
  3. Package dependencies: Know the difference between Depends, Recommends, Suggests
  4. Package states: Understand install, hold, auto, manual states
  5. Pinning: Higher priority wins (1000 = highest)
  6. dpkg vs apt: dpkg doesn’t resolve dependencies
  7. GPG keys: Modern systems use signed-by instead of apt-key
  8. Security: Always verify package authenticity
  9. Troubleshooting: dpkg --configure -a fixes most issues
  10. Clean up: apt-get autoremove removes unused dependencies

In this chapter, you learned:

  • ✅ apt architecture and components (apt, apt-get, apt-cache, dpkg)
  • ✅ Repository structure (main, universe, restricted, multiverse)
  • ✅ Package dependencies and states
  • ✅ Version management and pinning
  • ✅ Direct package management with dpkg
  • ✅ Package searching with apt-cache
  • ✅ Troubleshooting package issues
  • ✅ Configuration files and security best practices
  • ✅ Production scripts and automation

Chapter 28: dnf/yum - Red Hat Package Manager


Last Updated: February 2026