APT — Advanced Package Tool
{:.gc-basic}
Basic
APT is the high-level package manager for Debian and Ubuntu systems. It resolves dependencies automatically and communicates with online repositories.
Essential APT Commands
# Update the local package index (doesn't upgrade anything)
sudo apt update
# Upgrade all installed packages to their latest versions
sudo apt upgrade
# Full upgrade — may add/remove packages to satisfy deps
sudo apt full-upgrade
# Install one or more packages
sudo apt install nginx git build-essential
# Remove a package (keep config files)
sudo apt remove nginx
# Remove a package AND its config files
sudo apt purge nginx
# Remove unused packages that were auto-installed
sudo apt autoremove
# Clean downloaded .deb package cache
sudo apt clean # remove all cached .deb files
sudo apt autoclean # remove only outdated cached .debs
Searching and Inspecting
# Search for packages by name or description
apt search nginx
apt search "web server"
# Show detailed package information
apt show nginx
# List installed packages
apt list --installed
apt list --installed | grep python
# List packages that have upgrades available
apt list --upgradable
apt show output:
Package: nginx
Version: 1.22.1-9
Depends: nginx-common (= 1.22.1-9), libc6 (>= 2.28), libpcre3, ...
Installed-Size: 497 kB
Homepage: https://nginx.org
Description: small, powerful, scalable web/proxy server
dpkg — Debian Package Manager
{:.gc-basic}
dpkg is the low-level backend that APT uses. It installs local .deb files and provides detailed package inspection tools.
# Install a local .deb file
sudo dpkg -i package.deb
# Fix broken dependencies after manual dpkg install
sudo apt install -f
# Remove a package
sudo dpkg -r package_name
# List all installed packages
dpkg -l
dpkg -l | grep nginx
# List files installed by a package
dpkg -L nginx
# Find which package owns a file
dpkg -S /usr/sbin/nginx
# Show package info
dpkg -s nginx
# Get detailed info from a .deb file (not installed)
dpkg --info package.deb
dpkg --contents package.deb # list contents
dpkg -l format:
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.22.1-9 amd64 small, powerful, scalable web server
rc vim 2:9.0.1378-2 amd64 Vi IMproved - enhanced vi editor
ii= installed (desired + status both “Install”)rc= removed but config files remain
Repositories and PPAs
{:.gc-mid}
Intermediate
sources.list and sources.list.d
APT knows where to find packages through repository definitions:
cat /etc/apt/sources.list
# deb https://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse
# deb https://archive.ubuntu.com/ubuntu jammy-security main restricted
ls /etc/apt/sources.list.d/ # additional repo files (PPAs, third-party)
Adding a PPA (Personal Package Archive):
sudo add-apt-repository ppa:deadsnakes/python
sudo apt update
sudo apt install python3.12
Adding a repository manually (e.g., Docker official repo):
# 1. Add GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 2. Add repo definition
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
# 3. Update and install
sudo apt update && sudo apt install docker-ce
Holding Packages
Prevent a specific package from being upgraded:
sudo apt-mark hold linux-image-generic # hold
sudo apt-mark unhold linux-image-generic # release
apt-mark showhold # list held packages
APT Pinning
Fine-grained control over which version of a package to install, useful when mixing stable and backports repositories:
# /etc/apt/preferences.d/backports
Package: *
Pin: release a=jammy-backports
Pin-Priority: 400
Package: git
Pin: release a=jammy-backports
Pin-Priority: 900 # prefer backports version of git
Priorities: < 0 never install; 0–100 installed only if no other version; 100 default; > 1000 downgrade allowed.
apt-cache policy git # show available versions and priorities
Building Software from Source
{:.gc-adv}
Advanced
Sometimes a package isn’t available, is too old, or you need a custom build configuration. Building from source gives full control.
Autotools (configure / make / make install)
Most traditional Unix software uses the GNU autotools build system.
# Install build dependencies
sudo apt install build-essential
# Typical workflow
wget https://example.com/myapp-1.0.tar.gz
tar -xzf myapp-1.0.tar.gz
cd myapp-1.0
# 1. Configure — checks dependencies, sets install prefix, generates Makefile
./configure --prefix=/usr/local --enable-ssl --without-debug
# 2. Build
make -j$(nproc) # use all CPU cores
# 3. Test (if the project has a test suite)
make check
# 4. Install
sudo make install
# Uninstall (if supported)
sudo make uninstall
Useful configure flags:
./configure --help # list all options
./configure --prefix=/opt/myapp # install to /opt instead of /usr/local
./configure CC=clang # use clang instead of gcc
./configure CFLAGS="-O2 -march=armv7-a" # cross-compile flags
CMake
Modern C/C++ projects use CMake, which generates build files for your platform.
sudo apt install cmake
git clone https://github.com/example/project.git
cd project
mkdir build && cd build # out-of-source build (recommended)
# Configure
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_SHARED_LIBS=ON
# Build
cmake --build . -- -j$(nproc)
# Install
sudo cmake --install .
# List all CMake options
cmake .. -LH
Cross-compiling with CMake (for embedded boards):
# toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH /opt/sysroot)
cmake .. -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
Getting Build Dependencies Automatically
# Install build dependencies declared in the source package
sudo apt build-dep nginx
# Download source package
apt source nginx
Creating a .deb Package
{:.gc-adv}
Packaging your own software allows proper installation, upgrade, and removal via APT.
Minimal .deb Structure
myapp_1.0-1_amd64/
├── DEBIAN/
│ ├── control # required metadata
│ ├── postinst # post-install script (optional)
│ ├── prerm # pre-remove script (optional)
│ └── conffiles # list of config files (optional)
└── usr/
├── bin/
│ └── myapp # the binary
└── share/
└── doc/
└── myapp/
└── copyright
DEBIAN/control:
Package: myapp
Version: 1.0-1
Architecture: amd64
Maintainer: Eslam Mohamed <eslam@example.com>
Depends: libc6 (>= 2.17), libssl3
Description: My Application
This is a longer description of the application.
It can span multiple lines (start continuation lines with a space).
DEBIAN/postinst:
#!/bin/bash
set -e
systemctl daemon-reload
systemctl enable myapp
systemctl start myapp
# Set correct permissions
chmod 755 myapp_1.0-1_amd64/DEBIAN/postinst
# Build the package
dpkg-deb --build --root-owner-group myapp_1.0-1_amd64
# Install it
sudo dpkg -i myapp_1.0-1_amd64.deb
# Verify
dpkg -l myapp
dpkg -L myapp # list installed files
Interview Q&A
{:.gc-iq}
Interview Q&A
Q1 — Basic: What is the difference between apt remove and apt purge?
apt removeremoves the package binary but leaves configuration files on disk (under/etc).apt purgeremoves everything including configuration files. Usepurgewhen you want a clean slate before reinstalling, or to free disk space completely. You canpurgealready-removed packages:sudo apt purge nginxwill clean up configs even after the binary is gone (status showsrcindpkg -l).
Q2 — Basic: Why do you need to run apt update before apt install?
apt updatesynchronises the local package index (stored in/var/lib/apt/lists/) with the upstream repositories. Without it, APT may install an outdated version, fail to find a new package, or miss security updates. It does NOT upgrade anything — it just refreshes the list of available versions.
Q3 — Intermediate: How would you install a specific version of a package?
# List available versions
apt-cache policy nginx
# or
apt list -a nginx
# Install specific version
sudo apt install nginx=1.22.1-9
Q4 — Intermediate: What happens when you run dpkg -i package.deb and it fails with “dependency problems”?
dpkgdoes not resolve dependencies automatically — it simply refuses to configure the package if dependencies are unmet. Fix it withsudo apt install -f(orapt --fix-broken install), which instructs APT to resolve and install the missing dependencies, then retry configuration.
Q5 — Advanced: How would you cross-compile a package for an ARM board on an x86 machine?
- Install a cross-toolchain:
sudo apt install gcc-arm-linux-gnueabihf.- Set
CC,CFLAGS, and--hostflags to target the ARM architecture:./configure --host=arm-linux-gnueabihf --prefix=/usr CFLAGS="-march=armv7-a -mfpu=neon" make -j$(nproc)
- Copy the resulting binary to the target board (via SCP or by mounting the SD card image). For complex projects, use a sysroot (a copy of the target’s
/usrand/lib) and point--sysrootto it to resolve library dependencies correctly.
References
{:.gc-ref}
References
| Resource | Link |
|---|---|
man 8 apt |
APT command reference |
man 1 dpkg |
dpkg command reference |
man 5 apt_preferences |
APT pinning documentation |
| Debian Policy Manual | debian.org/doc/debian-policy |
| CMake documentation | cmake.org/documentation |
| Autotools tutorial | gnu.org/software/automake/manual |