Advanced APT Configuration and Usage

Topic Progress:

8.3. Advanced APT Configuration and Usage

Now it is time to dive into some more advanced topics. First, we will take a look at advanced configuration of APT, which will allow you to set more permanent options that will apply to APT tools. We will then show how package priorities can be manipulated, which opens the door for advanced fine-tuned, customized updates and upgrades. We will also show how to handle multiple distributions so that you can start experimenting with packages coming from other distributions. Next, we will take a look at how to track automatically installed packages, a capability that enables you to manage packages that are installed through dependencies. We will also explain how multi-arch support opens the door for running packages built for various hardware architectures. Last but not least, we will discuss the cryptographic protocols and utilities in place that will let you validate each package's authenticity.

8.3.1. Configuring APT

Before we dive into the configuration of APT, let's take a moment to discuss the configuration mechanism of a Debian-based system. Historically, configuration was handled by dedicated configuration files. However, in modern Linux systems like Debian and Kali, configuration directories with the .d suffix are becoming more commonly used. Each directory represents a configuration file that is split into multiple files. In this sense, all of the files in /etc/apt/apt.conf.d/ are instructions for the configuration of APT. APT processes the files in alphabetical order, so that the later files can modify configuration elements defined in the earlier files.

This structure brings some flexibility to administrators and package maintainers, allowing them to make software configuration changes through file additions without having to change an existing file. This is especially helpful for package maintainers because they can use this approach to adapt the configuration of other software to ensure that it perfectly co-exists with theirs, without breaking the Debian policy that explicitly forbids modifying configuration files of other packages. Because of the .d configuration mechanism, you don't have to manually follow multiple package configuration instructions typically found in the package's /usr/share/doc/package /README.Debian file, since the installer can drop in configuration files.

Beware of Configuration Files Generated from .d Directories

While APT has native support of its /etc/apt/apt.conf.d directory, this is not always the case. For some applications (like exim, for example), the .d directory is a Debian-specific addition used as input to dynamically generate the canonical configuration file used by the application. In those cases, the packages provide an "update-*" command (for example: update-exim4.conf) that will concatenate the files from the .d directory and overwrite the main configuration file.

In those cases, you must not manually edit the main configuration file as your changes will be lost on the next execution of the update-* command, and you must also not forget to run the former command after having edited a file out of the .d directory (or your changes will not be used).

Armed with an understanding of the .d configuration mechanism, let's talk about how you can leverage it to configure APT. As we have discussed, you can alter APT's behavior through command-line arguments to dpkg like this example, which performs a forced overwrite install of zsh:

apt -o Dpkg::Options::="--force-overwrite" install zsh

Obviously this is very cumbersome, especially if you use options frequently, but you can also use the .d directory configuration structure to configure certain aspects of APT by adding directives to a file in the /etc/apt/apt.conf.d/ directory. For example, this (and any other) directive can easily be added to a file in /etc/apt/apt.conf.d/. The name of this file is somewhat arbitrary, but a common convention is to use either local or 99local:

$ cat /etc/apt/apt.conf.d/99local
Dpkg::Options {

There are many other helpful configuration options and we certainly can't cover them all, but one we will touch on involves network connectivity. For example, if you can only access the web through a proxy, add a line like Acquire::http::proxy "http://yourproxy:3128". For an FTP proxy, use Acquire::ftp::proxy "ftp://yourproxy".

To discover more configuration options, read the apt.conf(5) manual page with the man apt.conf command (for details on manual pages, see Section 6.1.1, "Manual Pages").

8.3.2. Managing Package Priorities

One of the most important aspects in the configuration of APT is the management of the priorities associated with each package source. For instance, you might want to extend your Kali Linux system with one or two newer packages from Debian Unstable or Debian Experimental. It is possible to assign a priority to each available package (the same package can have several priorities depending on its version or the distribution providing it). These priorities will influence APT's behavior: for each package, it will always select the version with the highest priority (except if this version is older than the installed one and its priority is less than 1000).

APT defines several default priorities. Each installed package version has a priority of 100. A non-installed version has a priority of 500 by default but it can jump to 990 if it is part of the target release (defined with the -t command-line option or the APT::Default-Release configuration directive).

You can modify the priorities by adding entries in the /etc/apt/preferences file with the names of the affected packages, their version, their origin and their new priority.

APT will never install an older version of a package (that is, a package whose version number is lower than the one of the currently installed package) except when its priority is higher than 1000. APT will always install the highest priority package that follows this constraint. If two packages have the same priority, APT installs the newest one (whose version number is the highest). If two packages of same version have the same priority but differ in their content, APT installs the version that is not installed (this rule has been created to cover the case of a package update without the increment of the revision number, which is usually required).

In more concrete terms, a package whose priority is less than 0 will never be installed. A package with a priority ranging between 0 and 100 will only be installed if no other version of the package is already installed. With a priority between 100 and 500, the package will only be installed if there is no other newer version installed or available in another distribution. A package of priority between 501 and 990 will only be installed if there is no newer version installed or available in the target distribution. With a priority between 990 and 1000, the package will be installed except if the installed version is newer. A priority greater than 1000 will always lead to the installation of the package even if it forces APT to downgrade to an older version.

When APT checks /etc/apt/preferences, it first takes into account the most specific entries (often those specifying the concerned package), then the more generic ones (including for example all the packages of a distribution). If several generic entries exist, the first match is used. The available selection criteria include the package's name and the source providing it. Every package source is identified by the information contained in a Release file that APT downloads together with the Packages files. These files specify the origin, usually "Kali" for the packages from Kali's official mirrors and "Debian" for the packages from Debian's official mirrors, but the origin can also be a person's or an organization's name for third-party repositories. The Release file also provides the name of the distribution together with its version. Let's have a look at its syntax through some realistic case studies of this mechanism.

Priority of Kali-Bleeding-Edge and Debian Experimental

If you listed Debian experimental in your sources.list file, the corresponding packages will almost never be installed because their default APT priority is 1. This is of course a specific case, designed to keep users from installing experimental packages by mistake. The packages can only be installed by typing apt install package/experimental, assuming of course that you are aware of the risks and potential headaches of life on the edge. It is still possible (though not recommended) to treat packages of experimental like those of other distributions by giving them a priority of 500. This is done with a specific entry in /etc/apt/preferences:

Package: *
Pin: release a=experimental
Pin-Priority: 500

Let's suppose that you only want to use packages from Kali and that you only want Debian packages installed when explicitly requested. You could write the following entries in the /etc/apt/preferences file (or in any file in /etc/apt/preferences.d/):

Package: *
Pin: release o=Kali
Pin-Priority: 900

Package: *
Pin: release o=Debian
Pin-Priority: -10

In the last two examples, you have seen a=experimental, which defines the name of the selected distribution and o=Kali and o=Debian, which limit the scope to packages whose origin are Kali and Debian, respectively.

Let's now assume that you have a server with several local programs depending on the version 5.22 of Perl and that you want to ensure that upgrades will not install another version of it. You could use this entry:

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

The reference documentation for this configuration file is available in the manual page apt_preferences(5), which you can display with man apt_preferences.

Adding Comments in /etc/apt/preferences

There is no official syntax for comments in /etc/apt/preferences, but some textual descriptions can be provided by prepending one or more Explanation fields into each entry:

Explanation: The package xserver-xorg-video-intel provided
Explanation: in experimental can be used safely
Package: xserver-xorg-video-intel
Pin: release a=experimental
Pin-Priority: 500

8.3.3. Working with Several Distributions

Given that apt is such a marvelous tool, you will likely want to dive in and start experimenting with packages coming from other distributions. For example, after installing a Kali Rolling system, you might want to try out a software package available in Kali Dev, Debian Unstable, or Debian Experimental without diverging too much from the system's initial state.

Even if you will occasionally encounter problems while mixing packages from different distributions, aptmanages such coexistence very well and limits risks very effectively (provided that the package dependencies are accurate). First, list all distributions used in /etc/apt/sources.list and define your reference distribution with the APT::Default-Release parameter (see Section 8.2.3, "Upgrading Kali Linux").

Let's suppose that Kali Rolling is your reference distribution but that Kali Dev and Debian Unstable are also listed in your sources.list file. In this case, you can use apt install package/unstable to install a package from Debian Unstable. If the installation fails due to some unsatisfiable dependencies, let it solve those dependencies within Unstable by adding the -t unstable parameter.

In this situation, upgrades (upgrade and full-upgrade) are done within Kali Rolling except for packages already upgraded to another distribution: those will follow updates available in the other distributions. We will explain this behavior with the help of the default priorities set by APT below. Do not hesitate to use apt-cache policy (see "Using apt-cache policy") to verify the given priorities.

In this situation, upgrades (upgrade and full-upgrade) are done within Kali Rolling except for packages already upgraded to another distribution: those will follow updates available in the other distributions. We will explain this behavior with the help of the default priorities set by APT below. Do not hesitate to use apt-cache policy (see sidebar Using apt-cache policy) to verify the given priorities.

Everything relies on the fact that APT only considers packages of higher or equal version than the installed package (assuming that /etc/apt/preferences has not been used to force priorities higher than 1000 for some packages).

Using apt-cache policy

To gain a better understanding of the mechanism of priority, do not hesitate to execute apt-cache policy to display the default priority associated with each package source. You can also use apt-cache policy package to display the priorities of all available versions of a given package.

Let's assume that you have installed version 1 of a first package from Kali Rolling and that version 2 and 3 are available respectively in Kali Dev and Debian Unstable. The installed version has a priority of 100 but the version available in Kali Rolling (the very same) has a priority of 990 (because it is part of the target release). Packages in Kali Dev and Debian Unstable have a priority of 500 (the default priority of a non-installed version). The winner is thus version 1 with a priority of 990. The package stays in Kali Rolling.

Let's take the example of another package whose version 2 has been installed from Kali Dev. Version 1 is available in Kali Rolling and version 3 in Debian Unstable. Version 1 (of priority 990—thus lower than 1000) is discarded because it is lower than the installed version. This only leaves version 2 and 3, both of priority 500. Faced with this alternative, APT selects the newest version, the one from Debian Unstable. If you don't want a package installed from Kali Dev to migrate to Debian Unstable, you have to assign a priority lower than 500 (490 for example) to packages coming from Debian Unstable. You can modify /etc/apt/preferences to this effect:

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

8.3.4. Tracking Automatically Installed Packages

One of the essential functionalities of apt is the tracking of packages installed only through dependencies. These packages are called automatic and often include libraries.

With this information, when packages are removed, the package managers can compute a list of automatic packages that are no longer needed (because there are no manually installed packages depending on them). The command apt autoremove will get rid of those packages. Aptitude does not have this command because it removes them automatically as soon as they are identified. In all cases, the tools display a clear message listing the affected packages.

It is a good habit to mark as automatic any package that you don't need directly so that they are automatically removed when they aren't necessary anymore. You can use apt-mark auto package to mark the given package as automatic, whereas apt-mark manual package does the opposite. aptitude markauto and aptitude unmarkauto work in the same way, although they offer more features for marking many packages at once (see Section, "Aptitude"). The console-based interactive interface of aptitude also makes it easy to review the automatic flag on many packages.

You might want to know why an automatically installed package is present on the system. To get this information from the command line, you can use aptitude why package (apt and apt-get have no similar feature):

$ aptitude why python-debian
i   aptitude         Recommends apt-xapian-index
i A apt-xapian-index Depends    python-debian (>= 0.1.15)

8.3.5. Leveraging Multi-Arch Support

All Debian packages have an Architecture field in their control information. This field can contain either "all" (for packages that are architecture-independent) or the name of the architecture that it targets (like amd64, or armhf). In the latter case, by default, dpkg will only install the package if its architecture matches the host's architecture as returned by dpkg --print-architecture.

This restriction ensures that you do not end up with binaries compiled for an incorrect architecture. Everything would be perfect except that (some) computers can run binaries for multiple architectures, either natively (an amd64 system can run i386 binaries) or through emulators. Enabling Multi-Arch

Multi-arch support for dpkg allows users to define foreign architectures that can be installed on the current system. This is easily done with dpkg --add-architecture, as in the example below where the i386 architecture needs to be added to the amd64 system in order to run Windows applications using Wine. There is a corresponding dpkg --remove-architecture to drop support of a foreign architecture, but it can only be used when no packages of this architecture remain installed.

# dpkg --print-architecture
# wine
it looks like wine32 is missing, you should install it.
multiarch needs to be enabled first.  as root, please
execute "dpkg --add-architecture i386 & apt-get update &
apt-get install wine32"
Usage: wine PROGRAM [ARGUMENTS...]   Run the specified program
       wine --help                   Display this help and exit
       wine --version                Output version information and exit
# dpkg --add-architecture i386
# dpkg --print-foreign-architectures
# apt update
# apt install wine32
Setting up libwine:i386 (1.8.6-5) ...
Setting up vdpau-driver-all:i386 (1.1.1-6) ...
Setting up wine32:i386 (1.8.6-5) ...
Setting up libasound2-plugins:i386 (1.1.1-1) ...
Processing triggers for libc-bin (2.24-9)
# wine
Usage: wine PROGRAM [ARGUMENTS...]   Run the specified program
     wine --help                   Display this help and exit
     wine --version                Output version information and exit
# dpkg --remove-architecture i386
dpkg: error: cannot remove architecture 'i386' currently in use by the database
# dpkg --print-foreign-architectures

APT will automatically detect when dpkg has been configured to support foreign architectures and will start downloading the corresponding Packages files during its update process.

Foreign packages can then be installed with apt install package:architecture.

Using Proprietary i386 Binaries on amd64

There are multiple use cases for multi-arch, but the most popular one is the possibility to execute 32-bit binaries (i386) on 64-bit systems (amd64), in particular since several popular proprietary applications (like Skype) are only provided in 32-bit versions. Multi-Arch Related Changes

To make multi-arch actually useful and usable, libraries had to be repackaged and moved to an architecture-specific directory so that multiple copies (targeting different architectures) can be installed alongside one another. Such updated packages contain the Multi-Arch: same header field to tell the packaging system that the various architectures of the package can be safely co-installed (and that those packages can only satisfy dependencies of packages of the same architecture).

$ dpkg -s libwine
dpkg-query: error: --status needs a valid package name but 'libwine' is not: ambiguous package name 'libwine' with more than one installed instance

Use --help for help about querying packages.
$ dpkg -s libwine:amd64 libwine:i386 | grep ^Multi
Multi-Arch: same
Multi-Arch: same
$ dpkg -L libgcc1:amd64 | grep .so
$ dpkg -S /usr/share/doc/libwine/copyright
libwine:amd64, libwine:i386: /usr/share/doc/libwine/copyright

It is worth noting that Multi-Arch: same packages must have their names qualified with their architecture to be unambiguously identifiable. These packages may also share files with other instances of the same package; dpkg ensures that all packages have bit-for-bit identical files when they are shared. Also, all instances of a package must have the same version, therefore they must be upgraded together.

Multi-Arch support also brings some interesting challenges in the way dependencies are handled. Satisfying a dependency requires either a package marked Multi-Arch: foreign or a package whose architecture matches the one of the package declaring the dependency (in this dependency resolution process, architecture-independent packages are assumed to be of the same architecture as the host). A dependency can also be weakened to allow any architecture to fulfill it, with the package:any syntax, but foreign packages can only satisfy such a dependency if they are marked Multi-Arch: allowed.

8.3.6. Validating Package Authenticity

System upgrades are very sensitive operations and you really want to ensure that you only install official packages from the Kali repositories. If the Kali mirror you are using has been compromised, a computer cracker could try to add malicious code to an otherwise legitimate package. Such a package, if installed, could do anything the cracker designed it to do including disclose passwords or confidential information. To circumvent this risk, Kali provides a tamper-proof seal to guarantee—at install time—that a package really comes from its official maintainer and hasn't been modified by a third party.

The seal works with a chain of cryptographic hashes and a signature. The signed file is the Release file, provided by the Kali mirrors. It contains a list of the Packages files (including their compressed forms, Packages.gz and Packages.xz, and the incremental versions), along with their MD5, SHA1, and SHA256 hashes, which ensures that the files haven't been tampered with. These Packages files contain a list of the Debian packages available on the mirror along with their hashes, which ensures in turn that the contents of the packages themselves haven't been altered either.

The trusted keys are managed with the apt-key command found in the apt package. This program maintains a keyring of GnuPG public keys, which are used to verify signatures in the Release.gpg files available on the mirrors. It can be used to add new keys manually (when non-official mirrors are needed). Generally however, only the official Kali keys are needed. These keys are automatically kept up-to-date by the kali-archive-keyring package (which puts the corresponding keyrings in /etc/apt/trusted.gpg.d). However, the first installation of this particular package requires caution: even if the package is signed like any other, the signature cannot be verified externally. Cautious administrators should therefore check the fingerprints of imported keys before trusting them to install new packages:

# apt-key fingerprint
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
pub   rsa4096 2019-04-14 [SC] [expires: 2027-04-12]
      80D1 5823 B7FD 1561 F9F7  BCDD DC30 D7C2 3CBB ABEE
uid           [ unknown] Debian Archive Automatic Signing Key (10/buster) 
sub   rsa4096 2019-04-14 [S] [expires: 2027-04-12]

pub   rsa4096 2019-04-14 [SC] [expires: 2027-04-12]
      5E61 B217 265D A980 7A23  C5FF 4DFA B270 CAA9 6DFA
uid           [ unknown] Debian Security Archive Automatic Signing Key (10/buster) 
sub   rsa4096 2019-04-14 [S] [expires: 2027-04-12]

pub   rsa4096 2019-02-05 [SC] [expires: 2027-02-03]
      6D33 866E DD8F FA41 C014  3AED DCC9 EFBF 77E1 1517
uid           [ unknown] Debian Stable Release Key (10/buster) 

pub   rsa4096 2014-11-21 [SC] [expires: 2022-11-19]
      126C 0D24 BD8A 2942 CC7D  F8AC 7638 D044 2B90 D010
uid           [ unknown] Debian Archive Automatic Signing Key (8/jessie) 

pub   rsa4096 2014-11-21 [SC] [expires: 2022-11-19]
      D211 6914 1CEC D440 F2EB  8DDA 9D6D 8F6B C857 C906
uid           [ unknown] Debian Security Archive Automatic Signing Key (8/jessie) 

pub   rsa4096 2013-08-17 [SC] [expires: 2021-08-15]
      75DD C3C4 A499 F1A1 8CB5  F3C8 CBF8 D6FD 518E 17E1
uid           [ unknown] Jessie Stable Release Key 

pub   rsa4096 2017-05-22 [SC] [expires: 2025-05-20]
      E1CF 20DD FFE4 B89E 8026  58F1 E0B1 1894 F66A EC98
uid           [ unknown] Debian Archive Automatic Signing Key (9/stretch) 
sub   rsa4096 2017-05-22 [S] [expires: 2025-05-20]

pub   rsa4096 2017-05-22 [SC] [expires: 2025-05-20]
      6ED6 F5CB 5FA6 FB2F 460A  E88E EDA0 D238 8AE2 2BA9
uid           [ unknown] Debian Security Archive Automatic Signing Key (9/stretch) 
sub   rsa4096 2017-05-22 [S] [expires: 2025-05-20]

pub   rsa4096 2017-05-20 [SC] [expires: 2025-05-18]
      067E 3C45 6BAE 240A CEE8  8F6F EF0F 382A 1A7B 6500
uid           [ unknown] Debian Stable Release Key (9/stretch) 

pub   rsa4096 2012-03-05 [SC] [expires: 2023-01-16]
      44C6 513A 8E4F B3D3 0875  F758 ED44 4FF0 7D8D 0BF6
uid           [ unknown] Kali Linux Repository 
sub   rsa4096 2012-03-05 [E] [expires: 2023-01-16]

When a third-party package source is added to the sources.list file, APT needs to be told to trust the corresponding GPG authentication key (otherwise it will keep complaining that it can't ensure the authenticity of the packages coming from that repository). The first step is of course to get the public key. More often than not, the key will be provided as a small text file, which we will call key.asc in the following examples.

To add the key to the trusted keyring, the administrator can run apt-key add < key.asc. Another way is to use the synaptic graphical interface: its Authentication tab in the Settings → Repositories menu provides the ability to import a key from the key.asc file.

For people who prefer a dedicated application and more details on the trusted keys, it is possible to use gui-apt-key (in the package of the same name), a small graphical user interface that manages the trusted keyring.

Once the appropriate keys are in the keyring, APT will check the signatures before any risky operation, so that front-ends will display a warning if asked to install a package whose authenticity can't be ascertained.