LinuxXI · Package ManagementVersion pinning
Package pinning, holds, and version selection
What you'll learn
- Pin specific package versions in apt and dnf
- Use hold and version operators to lock a version
- Audit pinning state across the fleet
- Decide when pinning is appropriate
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09
Production fleets pin package versions for stability: every host runs the same version of every critical package, regardless of what the repositories now offer. Version pinning is the discipline that prevents “every host upgraded to a different version on Friday and now we have N bugs”.
Pinning in apt
$ sudo apt-mark hold openssh-server; apt-mark showholdopenssh-server set on hold.
openssh-server
Illustrative output
$ sudo tee /etc/apt/preferences.d/no-default-jdk.pref >/dev/null <<EOF
Package: default-jdk
Pin: release o=Ubuntu
Pin-Priority: 50
Package: default-jdk
Pin: version 17.*
Pin-Priority: 999
EOF
sudo apt update...Illustrative output
The bands are documented in apt_preferences(5) and the
boundaries matter — a pin of exactly 1000 does allow a downgrade,
and 990 is the line between “prefer” and “default”, not 900:
| Pin-Priority | Effect |
|---|---|
P >= 1000 | Installed even if it is a downgrade |
990 <= P < 1000 | Installed even if it does not come from the target release |
500 <= P < 990 | Installed unless a version from the target release is available — the default band |
100 <= P < 500 | Installed unless a version from some other distribution is available |
0 < P < 100 | Installed only if no version of the package is installed |
P < 0 | Never installed |
The 0 < P < 100 band is the one operators reach for and the one
most often missing from cheat sheets: it makes a repository
available for a deliberate apt install foo/bar without ever
letting apt upgrade pull from it.
Prove the pin took effect
A pin file that apt cannot parse is silently ignored — there is no error, the package just upgrades anyway. Never assume; ask:
apt-cache policy openssh-server # candidate version and the pin that chose it
apt-cache policy # priority of every configured origin
If apt-cache policy <package> does not show your pin priority
against the origin you pinned, the pin is not doing anything.
Pinning in dnf
$ sudo dnf install openssh-server-9.6p1-3.el9; sudo dnf versionlock add openssh-server; dnf versionlock list...Illustrative output
$ sudo dnf versionlock delete openssh-server; sudo dnf install openssh-server...Illustrative output
When to pin
| Pin? | Reason |
|---|---|
| Yes | Production-critical service (sshd, sudo, systemd, openssl) where a regression would cause widespread impact |
| Yes | Application with custom integration (a specific Java version, a specific Python version) |
| Yes | Security-sensitive package where you control the upgrade cycle |
| No | Standard libraries that the application does not depend on directly |
| No | Packages that you actively want to receive security updates for |
Auditing pinning state across the fleet
$ ansible all -m shell -a 'apt-mark showhold' 2>/dev/null | head...Illustrative output
Knowledge check
Knowledge check · 3 questions
Q1. What does `apt-mark hold openssh-server` do?
Q2. Pinning a package also blocks security updates for that package.
Q3. Which of the following are correct pinning practices? Select all that apply.
Passing score: 75%. Answers are checked in this browser.