Overview

Package management is foundational to Linux system administration. Debian-based systems use apt/dpkg, while Red Hat-based systems use yum/dnf/rpm. Understanding both package management ecosystems — their principles and usage — along with repository management, dependency resolution, package building, version pinning, and offline installation, is a prerequisite for efficient operations. This article systematically compares the two ecosystems and dives into practical package building and mirror optimization.

apt/dpkg Ecosystem

Architecture

apt (high-level frontend)
  
  ├── apt-get      package install/remove/update
  ├── apt-cache    package query/search
  └── apt          unified command (user-friendly)
  
dpkg (low-level tool)
  
  ├── dpkg         .deb package install/remove
  ├── dpkg-deb     .deb package operations
  └── dpkg-query   package query
  
aptitude (alternative frontend, optional)

apt vs apt-get

# apt combines apt-get and apt-cache with friendlier output
# Common comparison:

# Install
$ apt install nginx      # New (recommended for interactive use)
$ apt-get install nginx  # Old (recommended for scripts)

# Search
$ apt search nginx
$ apt-cache search nginx

# View package info
$ apt show nginx
$ apt-cache show nginx

# Update index
$ apt update
$ apt-get update

# Upgrade
$ apt upgrade            # Upgrade installed packages (no removal)
$ apt full-upgrade       # Upgrade (may remove packages to resolve dependencies)
$ apt-get dist-upgrade   # Equivalent to full-upgrade

In scripts, use apt-get/apt-cache for stable output format; for interactive use, apt is more user-friendly.

Basic Operations

# Install packages
$ apt install nginx
$ apt install nginx=1.24.0-1ubuntu1    # Install specific version
$ apt install -y nginx                  # Auto-confirm
$ apt install --no-install-recommends nginx  # Don't install recommended packages

# Remove
$ apt remove nginx        # Remove but keep config
$ apt purge nginx         # Remove and delete config
$ apt autoremove          # Remove unneeded dependencies
$ apt autoclean           # Clean obsolete deb files
$ apt clean               # Clean all deb files

# Update
$ apt update              # Update package index
$ apt upgrade             # Upgrade all packages
$ apt full-upgrade        # Upgrade (including dependency changes)
$ apt install --only-upgrade nginx  # Upgrade only specific package

# Query
$ apt list --installed        # Installed packages
$ apt list --upgradable       # Upgradable packages
$ apt show nginx              # Package details
$ apt search "web server"     # Search
$ apt depends nginx           # View dependencies
$ apt rdepends nginx          # View reverse dependencies
$ apt policy nginx            # View version and source

dpkg Low-Level Operations

# Install deb packages
$ dpkg -i package.deb      # Install
$ dpkg -i --force-depends package.deb  # Ignore dependencies (not recommended)

# Remove
$ dpkg -r package          # Remove (keep config)
$ dpkg -P package          # Remove (delete config)

# Query
$ dpkg -l                  # List all installed packages
$ dpkg -l nginx            # View specific package status
$ dpkg -L nginx            # List files installed by package
$ dpkg -S /usr/sbin/nginx  # Find which package owns a file
$ dpkg -s nginx            # View package details
$ dpkg -I package.deb      # View deb package info
$ dpkg -c package.deb      # View deb package contents

# Extract (without installing)
$ dpkg -x package.deb /tmp/extract
$ dpkg -e package.deb /tmp/extract/DEBIAN  # Extract control files

apt Package States

$ dpkg -l nginx
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version        Architecture Description
+++-==============-==============-============-=================================
ii  nginx          1.24.0-1       amd64        high performance web server
FieldValueMeaning
DesirediShould be installed
StatusiInstalled
Err(none)No error
Combined iiProperly installed
rcRemoved but config kept
hiInstalled and held
unNot installed

Fixing Broken Dependencies

# Fix dependencies
$ apt --fix-broken install
$ apt-get -f install

# Reconfigure installed packages
$ dpkg --configure -a

# Force reinstall
$ apt install --reinstall nginx
$ dpkg --force-all -i package.deb  # Last resort

yum/dnf/rpm Ecosystem

Architecture

dnf (successor to yum, Fedora/RHEL 8+)
  
  ├── dnf           package install/remove/update
  ├── dnf-config-manager  repository management
  └── dnf-utils     utility tools (repoquery, etc.)
  
yum (RHEL 7 and below)
  
rpm (low-level tool)
  
  ├── rpm           .rpm package install/remove
  ├── rpm2cpio      extract rpm
  └── rpmbuild      build rpm

yum vs dnf

# dnf commands are largely compatible with yum
# Key improvements:
# - Faster dependency resolution (libsolv)
# - Better memory usage
# - Modular support
# - Clearer error messages

# Common commands (work with both yum/dnf)
$ dnf install nginx
$ dnf remove nginx
$ dnf update nginx
$ dnf update             # Update all packages
$ dnf search nginx
$ dnf info nginx
$ dnf list installed
$ dnf list available
$ dnf history            # Operation history
$ dnf history undo 5     # Undo operation #5

Basic Operations

# Install
$ dnf install nginx
$ dnf install nginx-1.24.0    # Specific version
$ dnf install -y nginx        # Auto-confirm
$ dnf install --nogpgcheck nginx  # Skip GPG check (not recommended)
$ dnf reinstall nginx         # Reinstall

# Remove
$ dnf remove nginx            # Remove
$ dnf autoremove              # Remove unneeded dependencies
$ dnf remove --noautoremove nginx  # Don't auto-remove dependencies

# Update
$ dnf check-update            # Check for available updates
$ dnf update                  # Update all
$ dnf upgrade                 # Same as update
$ dnf update --security       # Only security updates

# Query
$ dnf list nginx              # View package
$ dnf info nginx              # Package details
$ dnf search "web server"     # Search
$ dnf provides /usr/sbin/nginx  # Find which package provides a file
$ dnf repoquery --requires nginx  # View dependencies
$ dnf repoquery --whatrequires nginx  # Reverse dependencies
$ dnf history                 # Operation history
$ dnf grouplist               # Package group list
$ dnf groupinstall "Development Tools"  # Install package group

rpm Low-Level Operations

# Install
$ rpm -ivh package.rpm       # Install
$ rpm -Uvh package.rpm       # Upgrade install
$ rpm -Fvh package.rpm       # Only upgrade if already installed
$ rpm -ivh --nodeps package.rpm  # Ignore dependencies (not recommended)
$ rpm -ivh --force package.rpm   # Force reinstall

# Remove
$ rpm -e package             # Remove
$ rpm -e --nodeps package    # Remove ignoring dependencies (dangerous)

# Query
$ rpm -qa                    # List all installed packages
$ rpm -q nginx               # Check if installed
$ rpm -qi nginx              # Package details
$ rpm -ql nginx              # Files installed by package
$ rpm -qc nginx              # Configuration files
$ rpm -qd nginx              # Documentation files
$ rpm -qf /usr/sbin/nginx    # Which package owns a file
$ rpm -qR nginx              # Dependencies
$ rpm -q --whatrequires nginx  # Reverse dependencies
$ rpm -q --changelog nginx   # Changelog

# Verify
$ rpm -V nginx               # Verify file integrity
$ rpm -Va                    # Verify all packages
# S=size changed M=permission changed 5=MD5 changed T=time changed

rpm Package Verification

$ rpm -V nginx
S.5....T.  c /etc/nginx/nginx.conf
# Field meanings:
# S - File size changed
# 5 - MD5 checksum changed
# L - Symlink changed
# T - Modification time changed
# D - Device changed
# U - User changed
# G - Group changed
# M - Permission changed
# . - This attribute unchanged

# Second column:
# c - Configuration file
# d - Documentation file
# g - Ghost file (should not exist)
# l - License file
# r - Readme file
# (empty) - Regular file

Repository Management

apt Repository Management

# View configured repositories
$ apt policy
$ cat /etc/apt/sources.list
$ ls /etc/apt/sources.list.d/

# Add repository (traditional method)
$ echo "deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse" >> /etc/apt/sources.list

# Add PPA
$ add-apt-repository ppa:nginx/stable
$ apt update

# Add repository (recommended method)
# /etc/apt/sources.list.d/nginx.list
deb [arch=amd64 signed-by=/etc/apt/keyrings/nginx.gpg] https://nginx.org/packages/ubuntu noble nginx

# Import GPG key
$ curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /etc/apt/keyrings/nginx.gpg

# Disable repository
# Comment out the line with #
# Or use apt preferences

# Update index
$ apt update

apt Repository Priority

# /etc/apt/preferences.d/nginx
Package: nginx
Pin: release o=nginx
Pin-Priority: 1001

# Priority explanation:
# 1001+  - Allow downgrade
# 990    - Default (installed version preferred)
# 500    - Standard priority
# 100    - Unofficial repository
# <0     - Refuse installation

# View priority
$ apt policy nginx

dnf/yum Repository Management

# View configured repositories
$ dnf repolist
$ dnf repolist --all

# Repository config file
$ ls /etc/yum.repos.d/
# /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

# Enable/disable repository
$ dnf config-manager --enable nginx-stable
$ dnf config-manager --disable nginx-stable

# Temporarily enable repository
$ dnf --enablerepo=nginx-stable install nginx

# Add repository
$ dnf config-manager --add-repo https://nginx.org/packages/centos/nginx.repo

# Import GPG key
$ rpm --import https://nginx.org/keys/nginx_signing.key

dnf Modularity

# View available modules
$ dnf module list

# Node.js module example
$ dnf module list nodejs
Name      Stream    Profiles                          Summary
nodejs    18        common [d], development, minimal  Javascript runtime
nodejs    20        common [d], development, minimal  Javascript runtime

# Enable module stream
$ dnf module enable nodejs:20

# Install module
$ dnf module install nodejs:20/common

# Switch module stream
$ dnf module reset nodejs
$ dnf module enable nodejs:18
$ dnf module install nodejs:18

Dependency Resolution

apt Dependency Resolution

# View dependencies
$ apt depends nginx
$ apt-cache depends nginx

# View reverse dependencies
$ apt rdepends nginx
$ apt-cache rdepends nginx

# View dependency tree
$ apt-cache depends --recurse nginx | head -50

# Find out why a package is installed
$ apt why nginx
# nginx <depends> nginx-core
# nginx-core <depends> nginx

# View package recommends and suggests
$ apt show nginx | grep -E "Depends|Recommends|Suggests"

dnf Dependency Resolution

# View dependencies
$ dnf repoquery --requires nginx
$ dnf repoquery --requires --recursive nginx

# Reverse dependencies
$ dnf repoquery --whatrequires nginx

# View package provides
$ dnf repoquery --provides nginx

# View package files
$ dnf repoquery --list nginx

# Dependency tree
$ dnf repoquery --requires --resolve --recursive nginx

Dependency Conflict Handling

# apt: Simulate installation to see conflicts
$ apt install -s nginx

# dnf: Use --best to show best available version
$ dnf install --best nginx

# dnf: Use --allowerasing to allow removing conflicting packages
$ dnf install --allowerasing nginx

# View conflict details
$ dnf install nginx --assumeno  # Simulate, answer no

Package Building

Building deb Packages

Directory Structure

mypackage/
├── DEBIAN/
│   ├── control          # Package info (required)
│   ├── postinst         # Post-installation script
│   ├── prerm            # Pre-removal script
│   ├── postrm           # Post-removal script
│   ├── preinst          # Pre-installation script
│   ├── conffiles        # Configuration file list
│   ├── md5sums          # File checksums (auto-generated)
│   └── triggers         # Triggers
├── usr/
│   ├── bin/
│   │   └── myapp        # Executable
│   ├── lib/
│   │   └── myapp/
│   │       └── config.yaml
│   └── share/
│       └── man/
│           └── man1/
│               └── myapp.1
└── etc/
    └── myapp/
        └── config.conf

control File

# mypackage/DEBIAN/control
Package: myapp
Version: 1.0.0
Architecture: amd64
Maintainer: Admin <admin@sre.wang>
Installed-Size: 1024
Depends: libc6 (>= 2.34), libssl3
Recommends: logrotate
Suggests: myapp-doc
Conflicts: oldapp
Replaces: oldapp
Section: utils
Priority: optional
Description: My Application
 A custom application for server management.
 .
 Features:
  - Feature 1
  - Feature 2

Maintenance Scripts

#!/bin/bash
# mypackage/DEBIAN/postinst

set -e

case "$1" in
    configure)
        # Create user
        if ! id myapp &>/dev/null; then
            useradd --system --no-create-home --shell /usr/sbin/nologin myapp
        fi
        
        # Set permissions
        chown myapp:myapp /var/lib/myapp
        chmod 750 /var/lib/myapp
        
        # Enable service
        systemctl enable myapp.service
        systemctl start myapp.service
        
        echo "myapp installed successfully"
        ;;
    
    abort-upgrade|abort-remove|abort-deconfigure)
        ;;
    
    *)
        echo "postinst called with unknown argument \`$1'" >&2
        exit 1
        ;;
esac

exit 0

Building

# Ensure correct permissions for control files
$ chmod 755 mypackage/DEBIAN/postinst
$ chmod 755 mypackage/DEBIAN/prerm

# Generate md5sums
$ cd mypackage
$ find . -type f ! -path './DEBIAN/*' -exec md5sum {} \; | sed 's/\.\///' > DEBIAN/md5sums

# Build deb package
$ dpkg-deb --build mypackage
# Or
$ dpkg -b mypackage myapp_1.0.0_amd64.deb

# Verify
$ dpkg-deb --info myapp_1.0.0_amd64.deb
$ dpkg-deb --contents myapp_1.0.0_amd64.deb

# Check with lintian
$ lintian myapp_1.0.0_amd64.deb

Building with debhelper (Advanced)

# Install build tools
$ apt install debhelper dh-make devscripts

# Initialize package
$ dh_make --createorig -p myapp_1.0.0

# Edit files in debian/ directory
# debian/control
# debian/rules
# debian/changelog

# Build
$ dpkg-buildpackage -us -uc -b

Building rpm Packages

spec File

# myapp.spec
Name:           myapp
Version:        1.0.0
Release:        1%{?dist}
Summary:        My Application

License:        MIT
URL:            https://sre.wang
Source0:        %{name}-%{version}.tar.gz

BuildRequires:  gcc
BuildRequires:  make
Requires:       openssl
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd

%description
A custom application for server management.

%prep
%setup -q

%build
make %{?_smp_mflags}

%install
make install DESTDIR=%{buildroot}
install -D -m 644 config/myapp.service %{buildroot}%{_unitdir}/myapp.service
install -D -m 644 config/myapp.conf %{buildroot}%{_sysconfdir}/myapp/myapp.conf

%files
%{_bindir}/myapp
%{_unitdir}/myapp.service
%dir %{_sysconfdir}/myapp
%config(noreplace) %{_sysconfdir}/myapp/myapp.conf
%doc README.md
%license LICENSE

%post
%systemd_post myapp.service

%preun
%systemd_preun myapp.service

%postun
%systemd_postun_with_restart myapp.service

%changelog
* Wed Jul 10 2026 Admin <admin@sre.wang> - 1.0.0-1
- Initial release

Building

# 1. Prepare build environment
$ dnf install rpmdevtools rpmbuild
$ rpmdev-setuptree

# 2. Directory structure
~/rpmbuild/
├── BUILD/
├── RPMS/
├── SOURCES/
│   └── myapp-1.0.0.tar.gz
├── SPECS/
│   └── myapp.spec
└── SRPMS/

# 3. Place source code
$ cp myapp-1.0.0.tar.gz ~/rpmbuild/SOURCES/
$ cp myapp.spec ~/rpmbuild/SPECS/

# 4. Build
$ rpmbuild -ba ~/rpmbuild/SPECS/myapp.spec
# -ba: Build src.rpm and binary rpm
# -bb: Build only binary rpm
# -bs: Build only src.rpm

# 5. View
$ ls ~/rpmbuild/RPMS/x86_64/
myapp-1.0.0-1.el9.x86_64.rpm

# 6. Verify
$ rpm -qpi ~/rpmbuild/RPMS/x86_64/myapp-1.0.0-1.el9.x86_64.rpm
$ rpm -qpl ~/rpmbuild/RPMS/x86_64/myapp-1.0.0-1.el9.x86_64.rpm

deb vs rpm Package Building Comparison

Featuredebrpm
Control fileDEBIAN/controlspec file
Script locationDEBIAN/ directoryInside spec file
Dependency declarationDepends/RecommendsRequires
Config file markingconffiles%config(noreplace)
Build tooldpkg-deb / debhelperrpmbuild
Source package.dsc + .orig.tar.gz.src.rpm
Changelogdebian/changelog%changelog

Version Pinning

apt Version Pinning

# Method 1: apt-mark hold
$ apt-mark hold nginx
$ apt-mark showhold
$ apt-mark unhold nginx

# Method 2: dpkg --set-selection
$ echo "nginx hold" | dpkg --set-selections
$ dpkg --get-selections | grep hold

# Method 3: apt preferences (more fine-grained)
# /etc/apt/preferences.d/hold-nginx
Package: nginx
Pin: release *
Pin-Priority: -1
# Priority < 0 refuses installation/upgrade

# Pin specific version
# /etc/apt/preferences.d/pin-nginx
Package: nginx
Pin: version 1.24.0*
Pin-Priority: 1001

dnf/yum Version Pinning

# Method 1: versionlock plugin
$ dnf install python3-dnf-plugin-versionlock
$ dnf versionlock add nginx
$ dnf versionlock list
$ dnf versionlock delete nginx
$ dnf versionlock clear

# Method 2: Exclude in repo
# /etc/yum.repos.d/centos.repo
[baseos]
exclude=nginx kernel*

# Method 3: dnf config
# /etc/dnf/dnf.conf
exclude=nginx

Offline Installation

Method 1: Download deb Packages and Dependencies

# Download package and all dependencies
$ apt download nginx
$ apt-get install --download-only -o Dir::Cache=/tmp/packages nginx
# Or
$ apt install --reinstall --download-only nginx

# Better approach: use apt-rdepends
$ apt install apt-rdepends
$ apt-rdepends nginx | grep -v "^ " | awk '{print $1}' | xargs apt download

# Using dpkg-offline
$ apt install dpkg-offline
$ dpkg-offline /path/to/iso nginx

# Install offline packages
$ dpkg -i /tmp/packages/*.deb
$ apt --fix-broken install  # Fix dependencies (if needed)

Method 2: Download rpm Packages and Dependencies

# Download package and dependencies
$ dnf install --downloadonly --downloaddir=/tmp/packages nginx

# Using repotrack
$ dnf install dnf-utils
$ repotrack nginx -p /tmp/packages

# Install offline packages
$ rpm -Uvh /tmp/packages/*.rpm
# Or
$ dnf localinstall /tmp/packages/*.rpm

Method 3: Create Local Repository

# apt local repository
$ apt install dpkg-dev
$ mkdir -p /opt/local-repo
$ cp *.deb /opt/local-repo/
$ cd /opt/local-repo && dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz

# Configure repository
# /etc/apt/sources.list.d/local.list
deb [trusted=yes] file:///opt/local-repo ./

$ apt update
$ apt install myapp

# dnf local repository
$ dnf install createrepo
$ mkdir -p /opt/local-repo
$ cp *.rpm /opt/local-repo/
$ createrepo /opt/local-repo

# Configure repository
# /etc/yum.repos.d/local.repo
[local]
name=Local Repository
baseurl=file:///opt/local-repo
gpgcheck=0
enabled=1

$ dnf install myapp

Method 4: Using Snapshots/Mirrors

# apt-mirror: full mirror
$ apt install apt-mirror
# /etc/apt/mirror.list
deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu noble-security main restricted universe multiverse

$ apt-mirror
# Downloads to /var/spool/apt-mirror/

# reposync: mirror dnf repository
$ dnf install dnf-utils
$ reposync --repoid=baseos --download_path=/opt/mirror
$ createrepo /opt/mirror/baseos

Mirror Optimization

Selecting the Fastest Mirror

# apt: netselect-apt
$ apt install netselect-apt
$ netselect-apt noble
# Auto-selects the fastest Ubuntu mirror

# Or manual testing
$ time curl -sI http://archive.ubuntu.com/ubuntu/ > /dev/null
$ time curl -sI http://mirrors.aliyun.com/ubuntu/ > /dev/null
$ time curl -sI http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ > /dev/null

# dnf: fastestmirror plugin
# /etc/dnf/dnf.conf
fastestmirror=True

$ dnf clean all
$ dnf makecache

Configuring Regional Mirrors

# Ubuntu/Debian mirror sources
# /etc/apt/sources.list
deb https://mirrors.aliyun.com/ubuntu/ noble main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-updates main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-security main restricted universe multiverse

# Or Tsinghua mirror
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ noble main restricted universe multiverse

# Debian
deb https://mirrors.aliyun.com/debian/ bookworm main contrib non-free non-free-firmware
deb https://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free non-free-firmware
deb https://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free non-free-firmware

# RHEL/CentOS mirror sources
# /etc/yum.repos.d/CentOS-Base.repo
[baseos]
name=CentOS Stream $releasever - BaseOS
baseurl=https://mirrors.aliyun.com/centos-stream/$releasever-stream/BaseOS/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

[appstream]
name=CentOS Stream $releasever - AppStream
baseurl=https://mirrors.aliyun.com/centos-stream/$releasever-stream/AppStream/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

# AlmaLinux/Rocky Linux
# Usually have regional mirrors available, refer to official docs

Mirror Cache Optimization

# apt: cache configuration
# /etc/apt/apt.conf.d/99-cache
Dir::Cache "/var/cache/apt";
Dir::Cache::archives "archives";
APT::Install-Recommends "false";  # Reduce unnecessary packages
APT::Install-Suggests "false";
APT::Get::Install-Suggests "false";

# Clean cache
$ apt clean          # Clean all downloaded deb files
$ apt autoclean      # Clean only obsolete deb files
$ apt autoremove     # Clean unneeded dependencies

# dnf: cache configuration
# /etc/dnf/dnf.conf
keepcache=True       # Keep downloaded rpm files
cachedir=/var/cache/dnf

$ dnf clean all      # Clean cache
$ dnf makecache      # Rebuild cache

Using Proxy

# apt proxy
# /etc/apt/apt.conf.d/99proxy
Acquire::http::Proxy "http://proxy.sre.wang:8080";
Acquire::https::Proxy "http://proxy.sre.wang:8080";

# Or environment variables
$ export http_proxy=http://proxy.sre.wang:8080
$ export https_proxy=http://proxy.sre.wang:8080
$ apt update

# dnf proxy
# /etc/dnf/dnf.conf
proxy=http://proxy.sre.wang:8080
proxy_username=user
proxy_password=pass

Package Management Security

GPG Key Management

# apt: GPG keys
# Import key (new method)
$ install -d /etc/apt/keyrings
$ curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /etc/apt/keyrings/nginx.gpg

# Import key (old method, not recommended)
$ apt-key add nginx_signing.key

# View imported keys
$ apt-key list

# Delete key
$ apt-key del ABC12345
$ rm /etc/apt/keyrings/nginx.gpg

# dnf: GPG keys
$ rpm --import https://nginx.org/keys/nginx_signing.key

# View imported keys
$ rpm -qa gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n'

# Delete key
$ rpm -e gpg-pubkey-abc12345

Verifying Package Integrity

# apt: verification
$ apt install --allow-unauthenticated nginx  # Disable verification (not recommended)
$ apt install nginx  # Default verification

# dpkg verification
$ debsums nginx    # Verify installed package files
$ debsums -c nginx # Check only changed files

# dnf: verification
$ dnf install --nogpgcheck nginx  # Disable verification (not recommended)

# rpm verification
$ rpm -K package.rpm     # Verify signature
$ rpm --checksig package.rpm

# Verify all installed packages
$ rpm -Va | grep -E "S\.5" | head -20
# Check if files have been tampered with

Real-World Examples

Example 1: Cross-Distribution Package Installation Script

#!/bin/bash
# install-packages.sh - Cross-distribution package installation

set -e

# Detect package manager
if command -v apt &>/dev/null; then
    PKG_MGR="apt"
elif command -v dnf &>/dev/null; then
    PKG_MGR="dnf"
elif command -v yum &>/dev/null; then
    PKG_MGR="yum"
else
    echo "Unsupported distribution"
    exit 1
fi

# Package name mapping (package names may differ across distributions)
declare -A PACKAGES=(
    ["nginx"]="nginx"
    ["redis"]="redis-server"  # Debian uses redis-server
    ["vim"]="vim"
    ["curl"]="curl"
    ["git"]="git"
)

# Install function
install_package() {
    local name=$1
    local apt_name=${2:-$1}
    local dnf_name=${3:-$1}
    
    case $PKG_MGR in
        apt)
            apt update && apt install -y "$apt_name"
            ;;
        dnf|yum)
            $PKG_MGR install -y "$dnf_name"
            ;;
    esac
}

# Batch install
for pkg in nginx redis vim curl git; do
    echo "Installing $pkg..."
    install_package "$pkg"
done

echo "All packages installed."

Example 2: Building a Custom Nginx Package

#!/bin/bash
# build-nginx-deb.sh - Build Nginx deb package

set -e

VERSION="1.27.0"
NGINX_USER="www-data"
BUILD_DIR="/tmp/nginx-build"
PKG_DIR="$BUILD_DIR/nginx_$VERSION"

# 1. Prepare build environment
apt install -y build-essential libpcre3-dev zlib1g-dev libssl-dev dpkg-dev

# 2. Download source
mkdir -p $BUILD_DIR
cd $BUILD_DIR
wget http://nginx.org/download/nginx-$VERSION.tar.gz
tar xzf nginx-$VERSION.tar.gz

# 3. Compile
cd nginx-$VERSION
./configure \
    --prefix=/usr/share/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --user=$NGINX_USER \
    --group=$NGINX_USER \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_stub_status_module
make -j$(nproc)
make install DESTDIR=$PKG_DIR

# 4. Create DEBIAN directory
mkdir -p $PKG_DIR/DEBIAN

# 5. Create control file
cat > $PKG_DIR/DEBIAN/control << EOF
Package: nginx-custom
Version: $VERSION
Architecture: amd64
Maintainer: Admin <admin@sre.wang>
Depends: libc6, libpcre3, zlib1g, libssl3
Section: web
Priority: optional
Description: Custom Nginx $VERSION
 Nginx built with custom configuration.
EOF

# 6. Create systemd service
mkdir -p $PKG_DIR/etc/systemd/system
cat > $PKG_DIR/etc/systemd/system/nginx.service << 'EOF'
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

# 7. Create postinst
cat > $PKG_DIR/DEBIAN/postinst << 'EOF'
#!/bin/bash
set -e
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx
EOF
chmod 755 $PKG_DIR/DEBIAN/postinst

# 8. Generate md5sums
cd $PKG_DIR
find . -type f ! -path './DEBIAN/*' -exec md5sum {} \; | sed 's/\.\///' > DEBIAN/md5sums

# 9. Build
cd $BUILD_DIR
dpkg-deb --build $(basename $PKG_DIR)

echo "Package built: $BUILD_DIR/nginx_$VERSION.deb"

Example 3: Automated Security Updates

#!/bin/bash
# auto-security-update.sh - Automated security update

set -e

LOG="/var/log/security-update.log"
exec > >(tee -a $LOG) 2>&1

echo "=== Security Update $(date) ==="

if command -v apt &>/dev/null; then
    # Debian/Ubuntu
    apt update
    
    # List only security updates
    apt list --upgradable 2>/dev/null | grep -i security
    
    # Use unattended-upgrades
    apt install -y unattended-upgrades
    echo 'APT::Periodic::Update-Package-Lists "1";' > /etc/apt/apt.conf.d/20auto-upgrades
    echo 'APT::Periodic::Unattended-Upgrade "1";' >> /etc/apt/apt.conf.d/20auto-upgrades
    
    unattended-upgrade --dry-run -v
    
elif command -v dnf &>/dev/null; then
    # RHEL/CentOS
    dnf check-update --security
    
    # Install security updates
    dnf update --security -y
    
    # Use dnf-automatic
    dnf install -y dnf-automatic
    sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
    sed -i 's/upgrade_type = default/upgrade_type = security/' /etc/dnf/automatic.conf
    systemctl enable --now dnf-automatic.timer
fi

echo "Security update completed."

Package Management Quick Reference

Operationapt/dpkgdnf/yum/rpm
Installapt install pkgdnf install pkg
Removeapt remove pkgdnf remove pkg
Remove + configapt purge pkgdnf remove pkg
Update indexapt updatednf makecache
Upgrade packageapt upgrade pkgdnf update pkg
Upgrade allapt full-upgradednf update
Searchapt search keyworddnf search keyword
Package infoapt show pkgdnf info pkg
Installed listapt list --installeddnf list installed
Find file ownerdpkg -S filerpm -qf file / dnf provides file
Package file listdpkg -L pkgrpm -ql pkg
Install local packagedpkg -i pkg.debdnf localinstall pkg.rpm
View dependenciesapt depends pkgdnf repoquery --requires pkg
Reverse dependenciesapt rdepends pkgdnf repoquery --whatrequires pkg
Pin versionapt-mark hold pkgdnf versionlock add pkg
Operation historycat /var/log/dpkg.logdnf history
Clean cacheapt cleandnf clean all

Summary

Linux package management is a foundational system administration skill — both ecosystems have their characteristics but share the same concepts. Key takeaways:

  1. apt/dpkg and dnf/rpm are two parallel ecosystems: Debian-based uses apt, Red Hat-based uses dnf (successor to yum), with dpkg and rpm as their respective low-level tools.
  2. Prefer high-level frontends: apt/dnf handle dependency resolution; dpkg/rpm only handle individual packages.
  3. Repository management is operations-critical: Properly configuring repository sources, GPG keys, and priorities is the prerequisite for safely using third-party software.
  4. Understand dependency resolution with Depends/Requires: apt depends/dnf repoquery --requires to view dependencies; apt why/dnf repoquery --whatrequires to find installation reasons.
  5. Package building requires understanding directory structure and control files: deb uses DEBIAN/control, rpm uses spec files; maintenance scripts handle service start/stop and permissions.
  6. Version pinning prevents accidental upgrades: apt-mark hold/dnf versionlock to lock critical packages, avoiding compatibility issues from automatic upgrades.
  7. Offline installation has multiple approaches: Download deb/rpm with dependencies, create local repositories, or use apt-mirror/reposync for mirroring.
  8. Mirror optimization improves installation speed: Use regional mirrors, configure cache, select fastest mirror.
  9. Security updates are an operations baseline: Use unattended-upgrades/dnf-automatic for automated security patching.
  10. GPG verification is the security foundation: Never use --allow-unauthenticated/--nogpgcheck; ensure package sources are trusted.

The golden rule of package management: minimal installation, maximum control. Install only the packages you need, pin critical package versions, regularly clean unneeded dependencies, and keep the system clean and manageable.