Using APT with more than 2 sources

APT's Default-Release setting (aka apt-get --target-release) is useful if your /etc/apt/sources.list file contains exactly 2 releases (such as stable and testing, or testing and unstable). If you want to track more than 2 releases (stable, testing, and unstable, or two of those plus a non-Debian source), it has problems. This document explains how to do better. Updates can be found at http://www.argon.org/~roderick/apt-pinning.html.

Improved /etc/apt/preferences File

First, here are some reasonable /etc/apt/preferences files for the common cases. The rest of this document describes what these are doing.

"apt-get --default-release" Has No Memory

When you run "apt-get -t unstable install foo", this sets APT::Default-Release for this invocation of apt-get, but it doesn't affect future runs. This is useful in some circumstances, but problematic in others.

The Good

Say you've got testing and unstable in your sources.list, an APT::Default-Release of "testing" in apt.conf, and a package foo which is available from the releases like this:

release version priority
no -t switch -t unstable
testing 1.1 990 500
unstable 1.2 500 990

If foo isn't installed and you run "apt-get install foo" you get version 1.1 from testing, since that version has the highest priority.

If you run "apt-get -t unstable install foo" instead you get version 1.2 from unstable, since the -t switch temporarily causes that version to have the highest priority.

foo will temporarily track unstable. If version 1.3 is uploaded to unstable while 1.1 is still in testing, we have:

release version priority
installed 1.2 100
testing 1.1 990
unstable 1.3 500

The highest priority version is 1.1, but this is lower than the installed 1.2. Since the priority of 1.1 is 990 (which is lower than 1000), apt-get will not downgrade to it. The next highest priority is 1.3 at 500. Since this is greater than the installed 1.1, it is selected.

foo will stop tracking unstable as soon as testing gets a version which is as new as the version which is currently installed. Say that version 1.3 migrates from unstable to testing, and then 1.4 is uploaded to unstable:

release version priority
installed 1.3 100
testing 1.3 990
unstable 1.4 500

Since the unstable 1.4 version now has a lower priority than the installed version, foo is not upgraded to it. Often this is what you want.

The Bad

APT::Default-Release's behavior works well when you're only tracking two different releases, but with 3 or more it starts to go wrong. When you install a package from 1 of the non-default releases, it can be immediately replaced with a newer version from another of them.

Consider:

release version priority
APT::Default-Release above /etc/apt/preferences
stable 1.0 990 900
testing 1.1 500 400
unstable 1.2 500 300

With an APT::Default-Release of "stable" and no /etc/apt/preferences, if you install the package with "apt-get -t testing install foo" you'll get version 1.1 from testing.

The big problem happens when you run "apt-get upgrade": Version 1.2 from unstable has the same priority as the 1.1 just installed, so 1.1 (testing) is replaced with 1.2 (unstable)!

I fix this problem by giving testing and unstable different priorities. With the explicit PINs from the above /etc/apt/preferences, version 1.2 from unstable has priority 300 compared to testing's 400, so the version from testing remains installed.

The pin of other Debian releases at priority -1 is only a bit of defensiveness. This doesn't affect any Debian sources that I know of (since they're all stable, testing, or unstable), so if a new Debian source is added I'll have to decide what priority to give it. Without this pin it'd come in at the default priority of 500.

Using Non-Debian Sources

If you're using non-Debian sources, you've got the same problem, only more so because there's no natural ordering as there is with Debian's stable -> testing -> unstable. Without explicitly listing them in /etc/apt/preferences, they're all at priority 500, so a package installed from one source can be replaced by a higher version supplied by a different source.

A partial fix for this is to pin each source at a different priority. Eg,

Package: *
Pin: origin marillat.free.fr
Pin-Priority: 600

Package: *
Pin: origin www.ibiblio.org
Pin-Priority: 610

Package: *
Pin: origin www.argon.org
Pin-Priority: 620

These settings would mean that a package installed from www.argon.org wouldn't automatically be replaced with one from the other two, and one from www.ibiblio.org wouldn't be replaced with one from ma marillat.free.fr.

Working in the other direction the packages would still be replaced, however: If you've installed a package from www.ibiblio.org and a newer version becomes available from www.argon.org, apt-get will upgrade to it. The only way I know of to prevent that is to explicitly pin the package to the source via /etc/apt/preferences.


Roderick Schertler <roderick@argon.org>
http://www.argon.org/~roderick/