How Linux Handles Package Holding and Pinning
Linux distributions rely on package managers to maintain system software, typically prioritizing the installation of the latest available versions during updates. However, specific use cases—such as maintaining application compatibility, preventing regressions, or preserving custom configurations—require freezing software at designated versions. Linux handles this through mechanisms known as package holding, locking, and pinning, which instruct the dependency solver to ignore upstream updates for targeted software. This guide covers how these mechanisms function across major package management systems, including APT, DNF/YUM, and Pacman.
The Underlying Mechanism
When an administrator runs an upgrade command, the package manager queries remote repositories, compares the version numbers of installed packages against upstream candidates, and builds a dependency resolution graph.
Package holding and pinning intercept this process:
- Holding/Locking: Sets a local administrative flag or rule that marks a package as ineligible for automatic replacement. The dependency solver simply skips the package during upgrade calculations.
- Pinning (Apt-Preferences): Assigns explicit numerical priorities to packages, releases, or repositories. If an installed version has a higher priority than an incoming update, the package manager suppresses the upgrade.
Debian, Ubuntu, and Derivatives (APT)
APT provides two primary approaches: quick state-based holding via
apt-mark, and granular priority-based control via APT
preferences.
1. State-Based Holding with
apt-mark
The apt-mark utility changes the metadata state of an
installed package directly in the /var/lib/dpkg/status or
APT internal state files.
- Hold a package:
sudo apt-mark hold <package-name> - Unhold a package:
sudo apt-mark unhold <package-name> - List held packages:
apt-mark showhold
2. Advanced Pinning with APT Preferences
For complex scenarios—such as tracking a package from a specific
release branch or pinning an exact version pattern—APT uses
configuration files in /etc/apt/preferences or
/etc/apt/preferences.d/.
A configuration block defines the target package, the pin rule, and a numerical priority:
Package: nginx
Pin: version 1.18.*
Pin-Priority: 1001
Understanding Pin-Priority values:
P >= 1000: Causes the package version to be installed even if it forces a downgrade.500 <= P < 990: Standard repository behavior; newer versions will overwrite older ones.100 <= P < 500: Installs the version, but does not upgrade it unless no other version is available.0 < P < 100: Prevents installation unless manually triggered.P < 0: Completely prevents the package version from being installed.
RHEL, Fedora, and CentOS (DNF and YUM)
Modern Red Hat-based distributions use DNF (or the legacy YUM), which
manages package retention through the versionlock plugin or
global configuration files.
1. The Versionlock Plugin
The versionlock plugin takes a snapshot of the package's
exact epoch, version, release, and architecture, storing it in
/etc/dnf/plugins/versionlock.list.
- Install the plugin:
sudo dnf install 'dnf-command(versionlock)' - Lock a package version:
sudo dnf versionlock add <package-name> - View locked packages:
sudo dnf versionlock list - Remove a lock:
sudo dnf versionlock delete <package-name>
2. Configuration Exclusion
For simpler restrictions without installing plugins, packages can be
excluded directly in /etc/dnf/dnf.conf:
[main]
exclude=kernel* mariadb*This blocks DNF from calculating updates or dependencies for any package matching the defined globs.
Arch Linux (Pacman)
Arch Linux avoids complex priority scoring and handles package locks
through directives in /etc/pacman.conf.
Using IgnorePkg
and IgnoreGroup
Open /etc/pacman.conf and locate the
[options] section:
- Lock specific packages:
IgnorePkg = linux linux-headers nodejs - Lock an entire package group:
IgnoreGroup = gnome
When running pacman -Syu, the package manager explicitly
prompts the user if it encounters an update for a package listed under
IgnorePkg, defaulting to skipping the upgrade unless
explicitly overridden by the operator.
openSUSE and SUSE Linux Enterprise (Zypper)
Zypper features native locking capabilities managed through its transaction engine.
- Add a lock:
sudo zypper addlock <package-name> - List active locks:
zypper locks - Remove a lock:
sudo zypper removelock <package-name>
Zypper stores these locks in /etc/zypp/locks, preventing
automatic installation, update, or removal during transaction
resolution.
Handling Dependency Conflicts on Held Packages
When a locked package is a dependency of another package marked for upgrade, the package manager faces a conflict:
- APT: Refuses to upgrade the dependent package, reporting that it has been "kept back."
- DNF: Aborts the transaction and outputs a broken
dependency warning unless
--nobestor--skip-brokenflags are supplied. - Pacman: Alerts the user to an unresolvable dependency loop, requiring manual user intervention to proceed.
To preserve system stability, package locks should be audited regularly to ensure that critical security patches are not unintentionally withheld.