apt_preferencesIn Debian and Ubuntu (and other Debian based distributions) you can use the /etc/apt/preferences file to maintain the various repositories. In the preferences file you can define whether packages should be installed from a certain repository defined in /etc/apt/sources.list and/or /etc/apt/sources.list.d/*.list. I will use Debian in my examples and will mention Ubuntu if it requires some extra attention.

Why would one use the preferences file?

Good question. I started using it when I wanted to install a teamspeak server on Debian Etch (the stable release back then) and the package was only available in Debian Lenny (testing). I do not download packages manually, I prefer apt to take care of it. But when I added the Lenny repositories I would upgrade my machine to testing, which is something I did not want to do. The preferences file allows you to mix your system, or to tell apt in which cases may be upgraded (or not).

How does it work?

Normally, without a preferences file all packages/repositories have a priority of 500, installed packages have a priority of a 100.
In Debian you can define a default/target release, eg lenny, APT::Default-Release “lenny”;. This will make sure packages from that release get a priority of 990. You can set the default release in /etc/apt/apt.conf. Doing this in Ubuntu is rather useless. The Ubuntu repositories are CODENAME-(updates|security|proposed|backports), and the default release doesn’t include these repositories. Because of this I don’t use this directive. I set the 990 priority in my preferences file (more on these numbers later).

You can look at the priorities of your repositories by running apt-cache policy or apt-cache policy packagename.

$ apt-cache policy hello
hello:
  Installed: (none)
  Candidate: 2.2-2
  Version table:
     2.4-3 0
        500 ftp://ftp.nl.debian.org testing/main Packages
        500 ftp://ftp.nl.debian.org unstable/main Packages
     2.2-2 0
        990 ftp://ftp.nl.debian.org lenny/main Packages

How does this influence package installations?

Apt determines normally based on the version of a package whether it should be installed. So if you have a repository which has an higher version of an installed package it will install that package. But now we have told apt what our default release is, apt will only update/install packages from that repository with the exception of packages which are not present on your default release repositories. If you track multiple repositories the default release alone will not be enough, and that is where the preferences files comes in. You can find the preferences file at /etc/apt/preferences, or not since it is doesn’t exist by default. In newer versions of apt you can also find the /etc/apt/preferences.d/ directory. The concept is similar to /etc/apt/sources.list and /etc/apt/sources.list.d. If you are using aptitude, please be aware that /etc/apt/preferences.d/* is ignored

In the preferences file you can tell apt how to deal with various repositories, eg mixing releases or using PPA’s with Ubuntu.

This would be my default preferences file if I would be running Debian stable. Please note that apt now supports # as comments, normally one would use Explanation: .

# Give preference to stable, then testing and finally unstable
# a=stable,n=lenny could also be a=stable, but you don't want to upgrade
# stable once testing becomes stable without you knowing about it.
# If you use testing/unstable feel free to pick any :)
#
# Ubuntu users can use a=CODENAME, where codename is
# dapper, hardy, intrepid, jaunty, karmic and all CODENAME-repos,
# eg hardy-updates, hardy-security, hardy-backports and hardy-proposed
#
Package: *
Pin: release a=stable,n=lenny
Pin-Priority: 990

Package: *
Pin: release a=testing
Pin-Priority: 600

Package: *
Pin: release a=unstable
Pin-Priority: 300

When running testing, I would set lenny to 300, testing to 990 and unstable to 600. If you wonder what the numbers mean, I’ve copied this from the apt_preferences(5) man page

P > 1000 causes a version to be installed even if this constitutes a downgrade of the package
990 < P <=1000 causes a version to be installed even if it does not come from the target release, unless the installed version is more recent
500 < P <=990 causes a version to be installed unless there is a version available belonging to the target release or the installed version is more recent
100 < P <=500 causes a version to be installed unless there is a version available belonging to some other distribution or the installed version is more recent
0 < P <=100 causes a version to be installed only if there is no installed version of the package
P < 0 prevents the version from being installed

Pinning packages

You can also pin packages from specific releases or versions.

Package: hello
Pin: release n=lenny
Pin-Priority: 995

# Or to a specific version
Package: hello
Pin: version 2.2-2
Pin-Priority: 990

# Or to anything in version 2.2, eg 2.2-4
Package: hello
Pin: version 2.2*
Pin-Priority: 990

You can see this here:

hello:
  Installed: (none)
  Candidate: 2.2-2
  Package pin: 2.2-2
  Version table:
     2.4-3 990
        600 ftp://ftp.nl.debian.org testing/main Packages
        990 ftp://ftp.nl.debian.org unstable/main Packages
     2.2-2 990
        990 ftp://ftp.nl.debian.org lenny/main Packages

Setting a package to a Pin-Priority above 1000 you will force a downgrade of a package when the version you want to be installed has a lower version then the currently installed package. If you do this, please execute aptitude -s install PACKAGENAME to see the consequences of that action. Please note that the package version pin preference is present on all versions, see this debian bug comment for more information.

Third-party repositories

Third party repositories could interfere with your regular preferences file, it will update packages which you don’t want to update. To remedy this, you can use apt-cache policy to determine some information about the repository.

$ apt-cache policy
# truncated for readability
 500 http://ppa.launchpad.net jaunty/main Packages
     release v=9.04,o=LP-PPA-ultrafredde,a=jaunty,n=jaunty,l=Ubuntu,c=main
     origin ppa.launchpad.net
# Everything from launchpad
Package: *
Pin: origin ppa.launchpad.net
Pin-Priority: 600

# One particular PPA
Package: *
Pin: release o=LP-PPA-ultrafredde
Pin-Priority: 600

You can now install packages and be sure they are not upgraded when you don’t want them to. Just fiddle with your preferences file and you can mix and match your system to your liking.

If you want to install packages which would normally not be installed, you can force aptitude to install other versions:

# Based on version, will install regardless of preferences file (assume prio 999)
aptitude install hello=2.4-3
# Based on release, will install with prio 990
aptitude install -t stable hello
# Based on release, will install regardless of preferences file (assume prio 999)
aptitude install hello/testing

We are now going to deny package installations from all launchpad origins but allow task to be installed. Task comes from a launchpad PPA.

# Deny everything from launchpad
Package: *
Pin: origin ppa.launchpad.net
Pin-Priority: -10

# Allow task
Package: task
Pin: origin ppa.launchpad.net
Pin-priority: 990

# Or based on the PPA itself:
Package: task
Pin: release o=LP-PPA-ultrafredde
Pin-priority: 990

With 3 small lines you can maintain a mixed system, Ubuntu 8.10 mixed with some 9.04 or Debian testing with unstable, or the otherway around. You can add PPA’s without having to worry about if it will update packages that you don’t want to be upgraded.