How to Block Package and Kernel Updates in Debian / Ubuntu

APT is probably the most useful tool for a Linux user. You can install, upgrade and remove any software/package from your Linux system with a single command. But sometimes, you need granular control over which package you want to install or upgrade and which package to block from being upgraded automatically. Why would you want to do this? Sometimes you find out that a package's updated version is buggy. You don't want that package to upgrade the next time you run sudo apt upgrade. And it is a pain to upgrade each package individually.

This tutorial will cover how to block certain packages from being installed or upgraded and how to block specific versions of packages or kernels from being installed.

Note: It is easy to forget what packages you have held after some time even when their bug-free versions are out. So remain on alert as holding packages for long can introduce security issues.

We will discuss two methods here. The first method will block all installs and upgrades for a certain package. The second method offers more granular control, allowing you to block specific versions of a package.

Prerequisites

  • A server with Ubuntu or Debian OS. Ubuntu 22.04 was used for this tutorial, but the commands here should also work fine with other Debian-based Operating systems and older releases.
  • A non-root user with sudo privileges.

Method 1 (apt-mark)

To lock a package from being installed, updated, or removed, we can use the apt-mark command.

If you want to hold a package, for example, htop from being installed, updated, or removed, use the following command.

$ sudo apt-mark hold htop

You should see the following output.

htop set on hold.

The locked package will remain on the same version even if you upgrade your system. This is especially useful for holding back graphics drivers.

To remove the hold on the package, issue the following command.

$ sudo apt-mark unhold htop

You should see the following output.

Canceled hold on htop.

There is an important caveat with this. While the package won't get automatically upgraded on using the command sudo apt upgrade or while upgrading the system, you can still remove the package manually. sudo apt remove <package> will still work on held packages.

This method only locks them from being changed automatically. Keeping them on hold will keep them at their current versions no matter what unless you decide to remove them manually.

Method 2 (/etc/apt/preferences)

This method involves editing the /etc/apt/preferences file where you can specify exactly what version of which package from which repository is installed.

Each package gets a numeric priority based on which APT decides whether to install the package or not and if yes then from which repository it should pick it up.

For example, let's check some details about the nginx package. Issue the following command.

$ apt-cache policy nginx

You should see a similar output.

nginx:
  Installed: (none)
  Candidate: 1.22.1-1~jammy
  Version table:
     1.22.1-1~jammy 500
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.22.0-1~jammy 500
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.20.2-1~jammy 500
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.18.0-6ubuntu14.3 500
        500 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
        500 http://us.archive.ubuntu.com/ubuntu jammy-security/main amd64 Packages
     1.18.0-6ubuntu14 500
        500 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 Packages

You will see that there are two repositories from where nginx installs. First is Ubuntu's repository and the second one is nginx's repository.

You can see 500 written against all repositories. This number specifies the package's priority. Since it is the same for all repositories, the chances of nginx coming from either of the repositories are the same. So how will the system decide which package to pick? It will pick the highest version that there is. In this case, it is 1.22.1. For Ubuntu, the complete version number becomes 1.22.1-1~jammy.

If you don't want to upgrade to the 1.22.1 version and want to block it, then you need to edit the /etc/apt/preferences file.

Open the file in the nano editor.

$ sudo nano /etc/apt/preferences

This command will also help you create the file if it didn't exist in the system previously.

Paste the following code in the file.

Package: nginx
Pin: version 1.22.1-1~jammy
Pin-Priority: -1

Setting the priority to anything lower than 0 means that the package won't get installed. If you want a package to always install, set its priority to 1000 or above.

Save the file by pressing Ctrl + X and entering Y when prompted.

Let's check the package again.

$ apt-cache policy nginx

You will see the following output.

nginx:
  Installed: (none)
  Candidate: 1.22.0-1~jammy
  Version table:
     1.22.1-1~jammy -1
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.22.0-1~jammy 500
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.20.2-1~jammy 500
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.18.0-6ubuntu14.3 500
        500 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
        500 http://us.archive.ubuntu.com/ubuntu jammy-security/main amd64 Packages
     1.18.0-6ubuntu14 500
        500 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 Packages

Notice any difference? The Candidate release version has dropped from 1.22.1 to 1.22.0. This means the next higher version that the system will now install is 1.22.0. You will also notice -1 written against the latest version which means the system should skip that version.

Skip one version but allow the other one

You can add multiple entries for the same package in the file. For example, add the following code to the file.

Package: nginx
Pin: version 1.22.1-1~jammy
Pin-Priority: -1

Package: nginx
Pin: version 1.20.2-1~jammy
Pin-Priority: 1000

Here we are telling the system to skip version 1.22.1 but always install the 1.20.2 version.

Let's check again using the apt-cache policy command.

nginx:
  Installed: (none)
  Candidate: 1.20.2-1~jammy
  Version table:
     1.22.1-1~jammy -1
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.22.0-1~jammy 500
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.20.2-1~jammy 1000
        500 http://nginx.org/packages/ubuntu jammy/nginx amd64 Packages
     1.18.0-6ubuntu14.3 500
        500 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
        500 http://us.archive.ubuntu.com/ubuntu jammy-security/main amd64 Packages
     1.18.0-6ubuntu14 500
        500 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 Packages

The candidate version has now shifted to 1.20.2 instead of 1.22.0.

Change the Repository preference

Let's consider one more case. What if we want to block Nginx from installing from its repository and choose the Ubuntu repository instead? One way would be to remove the Nginx repository but you can again use the preferences file to choose the repository for you.

Enter the following code in the file.

Package: nginx
Pin: release o=nginx
Pin-Priority: -1

The release keyword just specifies the next higher version. o=nginx refers to the origin of the package. Here it is nginx. This means the system shouldn't install the nginx package from its repository. Another way to achieve the same result is to use the following code.

Package: nginx
Pin: release o=jammy
Pin-Priority: 1000

This time we have set the priority 1000 of the Ubuntu (jammy) repository package. This will ensure that Nginx is always installed from the Ubuntu repository and not from anywhere else.

Not only you can specify the origin of the package, but you can also add the archive, component, label, and architecture of the package which the system should pick by using the following keywords under the Pin section.

  • c -> Component
  • a -> Archive
  • o -> Origin
  • l -> Label
  • n -> Architecture

Blocking Specific Kernel Updates

Let's see how we can block specific kernel upgrades. List all the kernel related packages on your system.

$ dpkg -l "*$(uname -r)*" | grep kernel | awk '{print $2}'

You will see a similar output.

linux-headers-5.15.0-33-generic
linux-image-5.15.0-33-generic
linux-modules-5.15.0-33-generic
linux-modules-extra-5.15.0-33-generic

The following methods will need to be repeated for all the packages obtained here.

Method 1 (apt-mark)

First, let's check what version of the kernel is active. To do that, run the following command.

$ uname -r

You should see a similar output.

5.15.0-53-generic

To prevent the kernel from being further upgraded, we can simply use the apt-mark command.

$ sudo apt-mark hold linux-image-$(uname -r)

You should see a similar output.

linux-image-5.15.0-53-generic set on hold.

You can follow the same method for blocking kernel headers by blocking the linux-headers-$(uname -r) package.

Method 2 (/etc/apt/apt.conf.d/50unattended-upgrades)

The second method involves the /etc/apt/apt.conf.d/50unattended-upgrades file.

Open it for editing.

$ sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Scroll down to the Unattended-Upgrade::Package-Blacklist section and edit as follows.

Unattended-Upgrade::Package-Blacklist {
"linux-generic";
"linux-image-generic";
"linux-headers-generic";
"linux-modules-generic";
"linux-modules-extra-generic";
};

Save the file by pressing Ctrl + X and entering Y when prompted.

Method 3 (dpkg)

To hold the kernel upgrade using dpkg, issue the following command. This command will hold all the kernel related packages at the same time.

$ for i in $(dpkg -l "*$(uname -r)*" | grep kernel | awk '{print $2}'); do echo $i hold | dpkg --set-selections; done

To remove the hold, use the following command.

$ for i in $(dpkg -l "*$(uname -r)*" | grep kernel | awk '{print $2}'); do echo $i install | dpkg --set-selections; done

Method 4 (/etc/apt/preferences)

Let's check the details regarding the current version of the kernel first.

$ apt-cache policy linux-image-$(uname -r)

You should see the following output.

linux-image-5.15.0-53-generic:
  Installed: 5.15.0-53.59
  Candidate: 5.15.0-53.59
  Version table:
 *** 5.15.0-53.59 500
        500 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
        500 http://us.archive.ubuntu.com/ubuntu jammy-security/main amd64 Packages
        100 /var/lib/dpkg/status

Even though 5.15.0.53 kernel is at its latest version as of writing this tutorial, we are supposing that the next version is already out (5.15.0.56 is the current stable Linux kernel version).

To block the next version of the kernel, enter the following code in the /etc/apt/preferences file.`

Package: linux-image-5.15.0-53-generic linux-headers-5.15.0-33-generic linux-modules-5.15.0-33-generic linux-modules-extra-5.15.0-33-generic
Pin: version 5.15.0-53.59
Pin-Priority: -1

The above code will block Ubuntu from installing any or all upgrades to the kernel.

You can follow methods 2 and 3 for any regular package, not just the kernel.

Conclusion

That's it for this tutorial. You should now be able to block any or specific versions of any packages you don't want to get installed or upgraded on your Ubuntu or Debian system. If you have any questions, post them in the comments below.

Share this page:

0 Comment(s)