335

I want to setup a new virtual machine with some specified packages (name and version), that are provided.

For example, apache2 in version 2.2.20-1ubuntu1 with all dependencies. Even if there is a new version of this package on the servers this one should be installed.

The solution has to work/scale with multiple (n) "setups". Another virtual machine might need an older version of apache2.

I currently know of some possibilities that install the exact packages, but do not scale that good:

  1. Copy all required *.deb to every virtual machine manually and enter: dpkg -i ... -> Could work, but it is very error-prone. (Manual scripts etc.)
  2. Create and use a new Ubuntu repository for each setup. -> Does not work because I would need n repositories.
  3. Setup the machine once and copy the VM / create a snapshot. -> Does not work because I would need to store n VMs.

My problem could be labeled as patch management, but I do not want to update my packages to the current version. My goal is to install old packages.

Pablo Bianchi
  • 15,657
ayckoster
  • 3,597

6 Answers6

329

You can use apt-get to install a specific version of the package a long as it is in an archive that apt knows about. From the apt-get manpage:

A specific version of a package can be selected for installation by following the package name with an equals and the version of the package to select. This will cause that version to be located and selected for install. Alternatively a specific distribution can be selected by following the package name with a slash and the version of the distribution or the Archive name (stable, frozen, unstable).

For example, you could do:

sudo apt-get install apache2=2.2.20-1ubuntu1

Note that you may need to do some dependency resolution on your own in this case, but if there are any problems apt-get will tell you what is causing them. On my 11.10 system I would need to do the following to get this to work:

sudo apt-get install apache2=2.2.20-1ubuntu1 \
                     apache2.2-common=2.2.20-1ubuntu1 \
                     apache2.2-bin=2.2.20-1ubuntu1 \
                     apache2-mpm-worker=2.2.20-1ubuntu1

You can display available package versions as follows:

sudo apt list -a apache2
fader
  • 5,571
97

To check which versions are available, you can check via:

sudo apt-cache madison ^apache2

If won't work, consider running sudo apt-get update before to update the package list.

Then copy the version or use the following syntax:

sudo apt-get install apache2=2.2.\*

To check which version you've installed, run:

dpkg -l 'apache2*' | grep ^i

If the version info is truncated, try:

COLUMNS=100 dpkg -l <packageName>
kenorb
  • 10,347
  • 14
    Thanks a lot for pointing out the =2.2\* option as a way to use a wildcard for selecting any available subversion. Thats what I wanted to know but didn't know how to ask :) – ᴍᴇʜᴏᴠ Apr 16 '15 at 14:31
  • 1
    N: Unable to locate package ^apache2 after $sudo apt-get update but sudo apt-get install apache2=2.2* works for me – Braian Mellor Jul 24 '17 at 15:04
  • 2
    @BraianMellor apt-get madison is obsolescence, use apt-get policy instead, apt-get policy ^apache2 is OK – netawater Aug 05 '20 at 05:28
  • sudo not needed for apt-cache; and apt-cache policy <pkg> is a similar alternative too, as a sidenote – creanion Sep 19 '22 at 09:45
  • The madison option on Ubuntu 22.* only shows the current version (and other commands in the answer either return errors or do not work) – TommyPeanuts Nov 26 '23 at 08:18
26

I'll expand on earlier answers with other handy versioning commands in the apt family. To see which versions are available, run apt-cache policy:

# apt-cache policy apache2
apache2:
  Installed: (none)
  Candidate: 2.4.7-1ubuntu4.5
  Version table:
     2.4.10-1ubuntu1.1~ubuntu14.04.1 0
        100 http://us.archive.ubuntu.com/ubuntu/ trusty-backports/main amd64 Packages
     2.4.7-1ubuntu4.5 0
        500 http://security.ubuntu.com/ubuntu/ trusty-security/main amd64 Packages
     2.4.7-1ubuntu4 0
        500 http://us.archive.ubuntu.com/ubuntu/ trusty/main amd64 Packages

Then, as mentioned elsewhere, install a specific version with apt-get:

# apt-get install apache2=2.4.7-1ubuntu4.5
...

You can now see which version you have installed by running apt-cache policy again:

# apt-cache policy apache2
apache2:
  Installed: 2.4.7-1ubuntu4.5
  Candidate: 2.4.7-1ubuntu4.5
  Version table:
     2.4.10-1ubuntu1.1~ubuntu14.04.1 0
        100 http://us.archive.ubuntu.com/ubuntu/ trusty-backports/main amd64 Packages
 *** 2.4.7-1ubuntu4.5 0
        500 http://security.ubuntu.com/ubuntu/ trusty-security/main amd64 Packages
        100 /var/lib/dpkg/status
     2.4.7-1ubuntu4 0
        500 http://us.archive.ubuntu.com/ubuntu/ trusty/main amd64 Packages

If you don't want newer versions to be installed on updates, pin the package with apt-mark:

# apt-mark hold apache2
apache2 set on hold.

Let's say a new version of apache2 is added to the package index and your machine is synced with apt-get update. You'll see this when you next run apt-get upgrade:

# apt-get upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
The following packages have been kept back:
  apache2
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
gsf
  • 361
10

As psusi explains, old versions are not kept in the ubuntu repository, but apparently you can still find them on launchpad. So, you go to (replace trusty and amd64 with your ubuntu version and architecture):

https://launchpad.net/ubuntu/trusty/amd64/apache2

and select the version you desire. Then you download the deb as a file and install with:

dpkg -i apache2_2.4.7-1ubuntu4.20_amd64.deb

Again, replace the filename to your file. This gets tedious if you have to downgrade a lot of packages but it's better than nothing if you're desperate.

soger
  • 731
  • 6
  • 8
5

Practically speaking, this isn't possible because the old versions are not kept in the archive, so unless you have a copy of the old version laying around somewhere, you can't install it. You should be asking yourself why you want to install an older version in the first place. On a stable release, the main reason for a new version being released is to correct a security vulnerability, and you don't want to be running a vulnerable server do you?

psusi
  • 37,551
  • 31
    I need this to reproduce exact copies of old environments for development purposes. Is it possible to setup a mirror that does not delete old package versions to access the required packages or do I need to setup multiple repositories that only hold diffs? – ayckoster Jan 02 '12 at 14:57
  • 1
    @ayckoster, sure, you can run your own mirror, or just manually save all of the packages you install for later ( they are cached in /var/cache/apt/archives ). – psusi Jan 03 '12 at 00:37
  • 24
    @psusi: Not exactly a fair response, there might be many reasons. In my case the newer version might actually have a bug, and to double check that is the case the older version is needed. Just an example. – Cookie Mar 28 '14 at 21:23
  • 1
    And this is why Ubuntu is actually 7 distros, each with a rolling release model. Right now, I'm stuck, unable to work on my cloud, because Ubuntu did a regression on a core package and I can't downgrade. – nomen Apr 05 '14 at 19:34
  • 2
    @nomen, no, it is a single distro that does not use a rolling release model. Great care is taken to ensure that when critical bugs and security vulnerabilities are fixed in the stable release, that they do not cause regressions, but if it does happen, then file a bug report tagged with regression-release and it will be fixed or rolled back. – psusi Apr 05 '14 at 23:48
  • @psusi: obviously, I filed a bug report. And it won't get fixed in time for me to do anything with it. And the older releases of the package have been removed from the archives. That is what makes each of Trusty, Precise, etc, a rolling release distro. Ubuntu is a brand, not a distro. – nomen Apr 05 '14 at 23:50
  • @nomen, that is not what rolling release means. A rolling release is one that gets new, updated software all the time, instead of remaining on the versions that were present at the time it was released, and getting only minor patches to address critical issues. – psusi Apr 05 '14 at 23:55
  • 1
    @psusi: the fact that I can't downgrade to the previous, non-broken version (so that I'm always using the "latest" version they offer) makes it a rolling release distro. Yes, I get that it's rolling and stable. But it is still rolling. – nomen Apr 06 '14 at 00:13
  • 5
    @nomen, if you want to make up your own meanings for words you will have a hard time communicating with others. For everyone else in the world, that is not what a rolling release is, and rolling release is the exact opposite, and thus, mutually exclusive with stable release. And now that I think about it, the original version shipped with the release is actually kept in the -release pocket, and updates go to the -updates or -security pocket, so while you can't go back to a previous update, you can go back to the originally released version. – psusi Apr 06 '14 at 01:17
  • 2
    @psusi: "A rolling release is one that gets new, updated software all the time, instead of remaining on the versions that were present at the time it was released" -- psusi. Guess what -- adding -1ubuntu to a version makes a software package a NEW VERSION. The important things about a rolling release is that IT IS ROLLING. You CAN'T GO BACK by official means. I am becoming irritated by your semantic quibbling with ZERO substance. – nomen Apr 06 '14 at 01:18
  • 1
    @nomen, no, it does not. New version means a new upstream version, which typically has lots of new features, and other changes, not just one critical bug fix. If you want an example of a rolling release, see arch, or debian unstable, or mint's rolling release. Every distro out there that calls itself a rolling release imports new upstream releases that add new features. Last year a number of people wanted to change Ubuntu to a rolling release model ( myself included ), but it was decided not to. – psusi Apr 06 '14 at 01:23
  • 1
    Perfect. So you are trying to redefine "new" to mean "upstream". That does not invalidate my point. It is you who is warping language to make a point. – nomen Apr 06 '14 at 01:25
  • 1
    @psusi: let me put it this way. "The old version worked, but the _______ does not." How should I fill in that blank in a way that satisfies your abuse of language? I think just about every English speaker would say "new" there. And yet, you accuse me of making up my own meanings for words. – nomen Apr 06 '14 at 01:34
  • @nomen, no, I am telling you how everyone else in the world defines a rolling release. It is you who is using a different defininition. – psusi Apr 07 '14 at 03:53
  • 8
    @psusi: Here is another one for you. Unison is required to always be the same version on all machines. Yet on 13.10 it is a different version than in 12.04 LTS. So now what? When coming to a question like this, receiving an answer like why do you want to do this is really incredibly unhelpful and a waste of time for everyone. – Cookie Apr 15 '14 at 07:01
  • @Cookie, what the heck are you talking about? Of course different releases have different versions, and running a package meant for one release on a completely different release is not supported. That is not what this question is about. – psusi Apr 15 '14 at 16:39
  • @psusi: From http://www.cis.upenn.edu/~bcpierce/unison/download/releases/stable/unison-manual.html: "It is important that the version of Unison installed on the server machine is the same as the version of Unison on the client machine." I am simply asking how one is to achieve that in your world, short of having every Ubuntu machine on the same release? – Cookie Apr 16 '14 at 13:41
  • 1
    @Cookie, build and install it locally rather than using the ubuntu repository. – psusi Apr 16 '14 at 19:36
  • @psusi: so you are saying rather than use the repository with =, we should if we want a specific version just always build from source? – Cookie Apr 17 '14 at 19:43
  • 2
    @Cookie, you can't use = since the repository only contains at most two versions: the one that was there at release, and the most recent update. If you want two wholly different releases to use the same version there is no supported way of doing that, hence why you have to build it from source yourself and deal with any problems that may arise from that. – psusi Apr 18 '14 at 22:03
  • 1
    @psusi: Ah I didn't realize that. I figured gcc had lots of versions, but looking closer, those are maintained as separate packages. – Cookie Apr 20 '14 at 06:54
  • 2
    Another reason to downgrade would be that some people have nothing better to do than rewrite software that was fine anyway and now thunderbird remained without a systray icon. So I would rather have some vulnerabilities that I'll never see than having to keep the thunderbird window open all the time. That is if I could downgrade to v 52. – soger Oct 17 '18 at 09:28
  • 1
    My apologies if this is the wrong place to make this remark, but this is a problem that tools like Docker are uniquely qualified to solve. If a problem is found with specific packages you can roll back to an earlier container image that contains the specific package versions you need. Additionally, for larger sites this is partially solved by use of a content caching proxy with a long expiration period for packages. – deoren Nov 01 '18 at 21:40
3

Also consider "wildcarding" the minor version

I've just learnt today that PPA minor versions are sometimes removed and replaced with another. E.g. it happened recently that the Git PPA https://launchpad.net/~git-core/+archive/ubuntu/ppa removed 1:2.36.0-0ppa1~ubuntu20.04.1 and replaced it with 1:2.36.1-0ppa1~ubuntu20.04.1. This then broke some Docker setup I had.

Luckily, I've found that wildcards do work on apt install, so I replaced the broken:

sudo apt install git=1:2.36.0-0ppa1~ubuntu20.04.1

with:

sudo apt install git='1:2.36.*'

Hopefully this will keep my scripts going for some longer.