APT Pinning in Debian: Choosing Package Versions Without a Full Upgrade
Learn how APT pinning controls Debian package priorities across stable, testing, and unstable, with a worked example and verification steps.
06 Oct 2026, 10:18 UTC

The problem: one newer package, not a newer system
You run Debian stable because you want predictable security updates. Then a project needs a library or server package that only exists in testing or unstable. Adding the extra suite and running a normal upgrade would drag in dozens of unrelated changes. APT pinning offers a narrower path: it tells the package manager which version to prefer, so you can pull a single package from a newer branch while leaving the rest of the system on stable.
The useful takeaway is that pinning is not magic—it is a set of priority numbers that APT compares before choosing a candidate version. If those numbers are wrong, you either get nothing new or you get a broken dependency chain. The commands below show how to set the numbers and how to confirm what APT will actually do before you change anything.
How APT priorities choose a version
On Debian systems using APT as shipped in recent stable and testing releases, every package version known to APT carries a priority. When multiple sources offer the same package, APT selects the version with the highest priority; if priorities tie, it picks the highest version number. On a standard system, versions from the configured suites—the named branches such as stable, testing, and unstable—usually receive a default priority of 500, while the version currently installed on disk receives 100. Pinning overrides these defaults with explicit integers.
Priorities above 1000 are special: they allow APT to downgrade a package if that is the only way to satisfy the rule. Values between 500 and 1000 make a version preferred over the defaults. Values below 100 make a version less likely to be chosen, but they do not prevent installation if no other version can satisfy a dependency. This last point matters—low priority is a preference, not a lock.
Writing a pin in /etc/apt/preferences
Pinning rules live in /etc/apt/preferences or in separate files under /etc/apt/preferences.d/ with no extension or a .pref extension. Each rule is a block, called a stanza, with three fields: Package names the target (a specific package, a glob pattern like *, or a regular expression in older configurations), Pin selects the origin, and Pin-Priority sets the integer weight.
The Pin line usually references a release attribute. Common attributes include a= for the archive or suite name (stable, testing, unstable), n= for the codename, and o= for the origin string recorded in the release file. If you are unsure which attributes your sources expose, run apt-cache policy with no arguments; it lists each repository and its priority.
Worked example: pulling nginx from unstable on a stable base
Suppose your sources.list includes stable, testing, and unstable, but you want the base system to stay on stable and only nginx to come from unstable. Create or edit /etc/apt/preferences.d/nginx-unstable.pref as root. The file needs two stanzas: one that keeps the general system at the stable default, and one that raises the unstable nginx above it.
Package: *
Pin: release a=stable
Pin-Priority: 900
Package: nginx
Pin: release a=unstable
Pin-Priority: 950
The first stanza gives every stable package a priority of 900, which is higher than the usual 500 and keeps stable dominant. The second stanza gives unstable nginx a priority of 950, so APT prefers it over the stable nginx. Because 950 is below 1000, APT will not downgrade nginx if a newer stable version appears later; it will simply switch back to stable when the stable version number exceeds the unstable one.
After saving the file, run apt-get update as root to refresh the package indexes. Then inspect the result as a normal user:
apt-cache policy nginx
The output lists every available version, its origin, and its assigned priority. The candidate—the version APT would install today—should be the unstable nginx with a priority of 950. If the candidate still points to stable, the release attribute in your Pin line probably does not match what the repository reports.
Simulating the upgrade before you run it
Before installing anything, ask APT what it would do. Run the following as root or with sudo:
apt-get -s upgrade
The -s flag simulates the transaction without changing the system. Read the list of packages carefully. If the simulation wants to upgrade libraries that nginx depends on from unstable, your pin is too narrow: the dependency solver is pulling in a partial upgrade. In that case, either widen the pin to cover the dependencies or accept that the package is not safely separable from its branch.
After a real upgrade, /var/log/apt/term.log records the transaction. Checking that log for warnings about held or pinned packages is a quick way to confirm that the rules behaved as intended.
The trade-off: preferences are not boundaries
The main limitation of pinning is that it influences choice; it does not enforce isolation. A package from unstable may depend on a newer library that is not in stable. APT will either pull that library from unstable or refuse the installation. Over time, a handful of narrowly pinned packages can accumulate enough unstable dependencies that your stable system is effectively a partial testing upgrade, with the associated risk that a security fix in stable is blocked by a pinned unstable version.
Conflicting rules are another hazard. If two files in /etc/apt/preferences.d/ assign different priorities to the same package, the effective behavior can be hard to predict. Keep pinning rules few, specific, and documented in comments.
A safer workflow
- Add the extra suite to
sources.listbut do not upgrade yet. - Write the narrowest pin that covers the package and its unavoidable dependencies.
- Run
apt-get update, thenapt-cache policy <package>to confirm the priority and candidate. - Run
apt-get -s upgradeand inspect the proposed changes. - If the simulation is acceptable, proceed with the real upgrade and review
/var/log/apt/term.log.
Pinning is a scalpel, not a hammer. Used narrowly and verified at each step, it lets you take a single newer package from testing or unstable without committing the whole machine to a branch change.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.