The Debian logo, by Raul Silva, licensed under CC BY-SA 3.0

How to pin packages in Debian

I use mostly Debian testing as my main operating system because of multiple reasons, two of which are:

  • nearly all programs I use are already packaged and maintained in Debian

  • the testing "branch" is up-to-date enough

No system is perfect; some packages might not be available or might be too old. In that case, it is possible to add other repositories.

This is not a complicated process, but what if two repositories provide the same package?

Until recently, I have never encountered such a situation; I try to avoid adding external sources whenever possible.

The trigger was VirtualBox. I had some incompatibilities with the package provided by Oracle with the current testing version (to be soon released as Trixie), and it also depends on at least one package that is not available anymore.

As long as it worked, my workaround was to download the one missing package and install it manually, but since I had other issues, I had to find another solution.

It turns out that VirtualBox is packaged for unstable/sid, and it is currently not planned to be released for testing and stable as it once was. The main reason is a disagreement between Debian and Oracle on how security issues should be handled 🗄️.

The next step was to install VirtualBox from Sid, since the unstable repository provides nearly all the packages that are in testing, I felt a bit uncomfortable. I looked into installing it, but because of the dependencies, it would not have been practical.

The first step is to add the Sid repository; just create the file /etc/apt/sources.list.d/sid.sources.

/etc/apt/sources.list.d/sid.sources
Types: deb deb-src
URIs: http://deb.debian.org/debian/
Suites: sid
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

The second and most important step is to tell the package manager to always prefer testing over sid unless instructed differently.

To do so, I’ve created two files in /etc/apt/preferences.d/

/etc/apt/preferences.d/testing.pref
Package: *
Pin: release a=testing
Pin-Priority: 100
/etc/apt/preferences.d/sid.pref
Package: *
Pin: release a=unstable
Pin-Priority: 10

Since Pin-Priority: 100 is greater than Pin-Priority: 10, packages from testing will take precedence over unstable.

If you want to be extremely sure you will not install a package accidentally from unstable, simply rename /etc/apt/sources.list.d/sid.sources to /etc/apt/sources.list.d/sid.sources.disabled.

At that point, synaptic marks the packages as "local or obsolete", which I find annoying, but if you do not touch them, there will be no harm.

Seeing how simple it is to mix two Debian repositories, I’m reconsidering my current approach.

I usually use Debian testing because sometimes I need programs that are not available or too "old" in Debian stable. I’m pretty happy with this approach, except for those times when a lot of packages change.

This happened recently, in order to support dates beyond 2028 on 32-bit system 🗄️, and normally when some big frameworks, like KDE, GNOME, or MATE have a major update. Most of the time it is not an issue, but one needs to pay some attention, and do system backups!

The other drawback is that newer does not always mean better, as newer versions might also remove features.

With Debian stable, those are non-issues.

What I wrote about missing and outdated versions, does not actually hold for most programs. I generally do not care if I have the latest version unless it is missing a feature I need or want to use.

Maybe next time I could install a stable system, add the testing repository with a lower Pin-Priority (Backports would actually be better), and then an unstable version, with an even lower Pin-Priority if I really need to.

Granted, mixing versions meets the definition of creating FrankenDebian 🗄️, which can lead to issues. If the amount of packages coming from a different version is low, the risk of breaking something should also be low.

If you are wondering what might break, consider that a package compiled for unstable might be built with different settings or a different compiler version. This might make the program incompatible with an already installed and used system library, even if the source code is the same. Thus, to have a working program, one needs to update a system library too, which in turn will be incompatible with other components of the system.

In practice, mixing packages generally works often enough that you’ll get a false sense of security. One notable example of incompatibilities was during the introduction of C++11. The compiler (at the time gcc 5 🗄️) broke the ABI to implement the newer standard, which meant that mixing packages during that period most surely caused issues.


Do you want to share your opinion? Or is there an error, some parts that are not clear enough?

You can contact me anytime.