apt-mark Holding a pacakge to a major version (not a specific minor)

I want to hold versions of packages on my servers to prevent breaking changes in infrastructure from breaking our code (Changes from mongodb 2.4 to 2.6 for example..)

I know I can (for example) apt-mark hold package for example, but then I stop getting security patches and minor upgrades.

Also I would like to install packages with setting a major version (but not a minor)

for example I know I can:

sudo apt-get install -y rabbitmq-server=3.3.5

But I want to just pin installation to a major version (3.*)

How can this be achieved?


You can pin to a wildcard set of version numbers. See man apt_preferences for an example:

The specific form assigns a priority (a "Pin-Priority") to one or more specified packages with a specified version or version range. For example, the following record assigns a high priority to all versions of the perl package whose version number begins with "5.10". Multiple packages can be separated by spaces.

Package: perl
Pin: version 5.10*
Pin-Priority: 1001

So, for example, on Ubuntu 16.04, where xenial-backports has a default priority of 100, the initial policy for debhelper is:

$ apt-cache policy debhelper
debhelper:
  Installed: 9.20160115ubuntu3
  Candidate: 9.20160115ubuntu3
  Version table:
     10.2.2ubuntu1~ubuntu16.04.1 100
        100 http://jp.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 http://jp.archive.ubuntu.com/ubuntu xenial-backports/main i386 Packages
 *** 9.20160115ubuntu3 500
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 Packages
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main i386 Packages
        100 /var/lib/dpkg/status

Then, I pinned backports to a higher priority:

$ cat /etc/apt/preferences.d/debhelper
Package: *
Pin: release v=16.04,o=Ubuntu,a=xenial-backports,n=xenial,l=Ubuntu,c=main,b=amd64
Pin-Priority: 600

$ apt-cache policy debhelper
debhelper:
  Installed: 9.20160115ubuntu3
  Candidate: 10.2.2ubuntu1~ubuntu16.04.1
  Version table:
     10.2.2ubuntu1~ubuntu16.04.1 600
        600 http://jp.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 http://jp.archive.ubuntu.com/ubuntu xenial-backports/main i386 Packages
 *** 9.20160115ubuntu3 500
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 Packages
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main i386 Packages

Again pinning 9.* versions of debhelper to an even higher priority:

$ cat /etc/apt/preferences.d/debhelper
Package: *
Pin: release v=16.04,o=Ubuntu,a=xenial-backports,n=xenial,l=Ubuntu,c=main,b=amd64
Pin-Priority: 600

Package: debhelper
Pin: version 9.*
Pin-Priority: 800

$ apt-cache policy debhelper
debhelper:
  Installed: 9.20160115ubuntu3
  Candidate: 9.20160115ubuntu3
  Version table:
     10.2.2ubuntu1~ubuntu16.04.1 600
        600 http://jp.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 http://jp.archive.ubuntu.com/ubuntu xenial-backports/main i386 Packages
 *** 9.20160115ubuntu3 800
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 Packages
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main i386 Packages
        100 /var/lib/dpkg/status

So you just need to create a file in /etc/apt/preferences.d/ that has:

Package: rabbitmq-server
Pin: version 3.*
Pin-Priority: 1001

No repository has a priority greater than 1000 by default, 1001 is enough to force apt to downgrade if needed:

P >= 1000 causes a version to be installed even if this constitutes a downgrade of the package.