Package downgrades and holds can leave dependencies inconsistent. Document what you change and test services after any rollback.
What you will achieve
Pin packages at their current version so apt upgrade skips them — useful for kernel holds, custom builds, or compatibility with proprietary drivers.
1) Hold a package
sudo apt-mark hold package-name
apt-mark showhold
2) Upgrade everything except held packages
sudo apt update
sudo apt upgrade -y
Held packages stay put; dependencies may still upgrade unless they require the held version.
3) Release hold when ready
sudo apt-mark unhold package-name
4) Alternative: apt pinning
For finer control, use /etc/apt/preferences.d/ with pin priorities — common for keeping a specific PHP or PostgreSQL major on LTS servers.
Verify
apt-cache policy package-name
Look for "Held packages" in apt output and confirm the candidate version matches your intent.
5) Hold kernel metapackages
sudo apt-mark hold linux-image-generic linux-headers-generic
Common when proprietary DKMS modules lag behind new kernels. Remember to unhold periodically for security patches.
6) Show why apt wants to upgrade
apt-cache rdepends package-name
apt why-not package-name
7) dpkg hold vs apt-mark
echo package hold | sudo dpkg --set-selections is the older mechanism. apt-mark hold is preferred on modern systems. Check both if holds behave unexpectedly:
dpkg --get-selections | grep hold
Documentation discipline
Record holds in your runbook or Ansible vars. Six months later nobody remembers why nginx was pinned at 1.18.
8) Team coordination
If one admin holds nginx and another runs blind full-upgrade, expect confusion. Store holds in git-tracked /etc/apt/preferences.d/ with comments.
9) Ansible apt hold module
- name: Hold nginx version
ansible.builtin.dpkg_selections:
name: nginx
selection: hold
Infrastructure-as-code teams should encode holds in Ansible/Terraform null resources rather than manual apt-mark on each server.
Prerequisites
Know exact package name (dpkg -l | grep nginx). Understand security implications of holding — document ticket number or change request. Sudo access required.
Verify hold survived dist-upgrade
sudo apt full-upgrade -s | grep package-name
Dry-run simulate shows whether apt would upgrade held package — should show no change.
Jenkins/CI apt pin
CI images baking held packages need Dockerfile ARG documenting hold reason — rebuild image when unholding for security cycle.
Release engineering workflow
When preparing a gold master image, bake holds into cloud-init or preseed so every instance starts with the same pin — drift between nodes causes mysterious version skew in clusters. Before major OS upgrade, export hold list, complete upgrade, then re-evaluate each hold: security team signs off on retained pins. Use apt-mark showhold > /root/holds-$(date +%F).txt in monthly backup cron for audit trail.