Report this

What is the reason for this report?

apt-key Deprecation: Add Repositories with GPG on Ubuntu

Updated on March 23, 2026
apt-key Deprecation: Add Repositories with GPG on Ubuntu

Introduction

apt-key is a utility used to manage the keys that APT uses to authenticate packages. It is closely related to the add-apt-repository utility, which adds external repositories using keyservers to an APT installation’s list of trusted sources. However, keys added using apt-key and add-apt-repository are trusted globally by APT. These keys are not limited to authorizing the single repository they were intended for. Any key added in this manner can be used to authorize the addition of any other external repository, presenting an important security concern. For more on APT and package management basics, see our guide on Package Management Essentials: apt, yum, dnf, pkg.

Starting with Ubuntu 20.10, the use of apt-key began generating deprecation warnings. Since then, apt-key has been deprecated and removed in newer Ubuntu releases, with stricter enforcement in Ubuntu 24.04 and later. While it may still function in Ubuntu 22.04, it is no longer recommended and should be avoided in modern systems.

The current best practice is to use gpg in place of apt-key and add-apt-repository. These tools have always acted as wrappers that call gpg in the background, so using gpg directly removes the intermediary while providing more control. More importantly, this approach allows you to store keys as keyring files (typically in /etc/apt/keyrings) and explicitly associate them with repositories using the signed-by option, ensuring that each key is only trusted for its intended source.

This tutorial will outline two procedures that use alternatives to apt-key and add-apt-repository, respectively. First, you will add an external repository using a public key with gpg instead of apt-key. Second, as an addendum, you will cover adding an external repository using a keyserver with gpg as an alternative to add-apt-repository.

In addition, this guide will cover migrating existing systems that use legacy key storage, handling upgrade issues introduced in Ubuntu 24.04, and applying these practices in automation workflows.

Key Takeaways:

  • The apt-key command has been deprecated since Ubuntu 20.10 and removed in Ubuntu 24.04 and later due to fundamental security vulnerabilities in its global trust model.
  • Storing repository signing keys in global keyrings creates a serious security risk because any key added to /etc/apt/trusted.gpg or /etc/apt/trusted.gpg.d/ can authenticate packages from any repository on the system, not just the one it was intended for.
  • Modern APT security requires storing keys as individual files in /etc/apt/keyrings and explicitly linking them to their repositories using the signed-by option, ensuring each key can only authenticate its designated repository.
  • ASCII-armored PGP keys must be converted to binary GPG keyring format using gpg --dearmor before APT can use them, as APT only accepts keys in binary .gpg format for repository authentication.
  • Every modern repository configuration must include the signed-by=/etc/apt/keyrings/<keyring>.gpg parameter in its definition, otherwise APT cannot determine which key to use and will fail to authenticate the repository.
  • Repository entries can be managed in three equivalent ways: adding lines directly to /etc/apt/sources.list, creating separate .list files in /etc/apt/sources.list.d/, or using the structured deb822 format in .sources files.
  • Systems upgraded to Ubuntu 24.04 require manual migration of existing repositories by exporting keys from legacy keyrings, saving them to /etc/apt/keyrings, updating repository definitions with signed-by options, and removing the old globally-trusted keys.
  • Automation workflows in Docker, shell scripts, and Ansible that rely on apt-key add must be completely rewritten to use the gpg --dearmor approach with scoped keyrings to maintain compatibility with modern Ubuntu releases and improve security.
  • Understanding directory purposes is critical: /etc/apt/keyrings stores administrator-managed keys, /usr/share/keyrings contains package-managed keys, and /etc/apt/trusted.gpg.d/ represents the deprecated legacy approach that should be avoided.
  • While keys can be retrieved from keyservers using gpg --recv-keys, downloading them directly via HTTPS is more reliable and avoids potential issues with slow, unreliable, or blocked keyservers, though both methods work with scoped keyrings.

Prerequisites

To complete this tutorial, you will need an Ubuntu 24.04 server. Be sure to set this up according to our initial server setup guide for Ubuntu, with a non-root user with sudo privileges and a firewall enabled.

Why apt-key Was Deprecated

The deprecation of apt-key is primarily due to security limitations in how APT handles trusted keys.

When you add a key using apt-key, it is stored in a global keyring (such as /etc/apt/trusted.gpg or /etc/apt/trusted.gpg.d/). Any key added to this keyring is trusted by APT for all configured repositories, not just the repository it was intended for.

This global trust model introduces a significant security risk. A key that was added for one repository can be used to authenticate packages from another repository. In a worst-case scenario, if a key is compromised or a malicious repository is added, it could be used to install untrusted packages without additional verification.

This behavior violates the principle of least privilege, where access should be limited to only what is necessary. In this case, a repository signing key should only be trusted to authenticate packages from its own source. For more information on securing your server, refer to Recommended Security Measures to Protect Your Servers.

To address this issue, modern versions of APT support a more secure approach using scoped keyrings. Instead of trusting keys globally, you store them as individual keyring files (typically under /etc/apt/keyrings) and explicitly associate each key with a repository using the signed-by option.

For example:

deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com stable main

With this configuration, the specified key is only used to authenticate packages from that repository. Even if other repositories are configured on the system, they cannot use this key unless explicitly allowed.

This change improves the security of package management by isolating trust between repositories and reducing the risk of unauthorized package installation. As a result, apt-key has been deprecated and removed in newer Ubuntu releases, and using scoped keyrings with gpg is now the recommended standard.

Step 1 — Identifying the Components and Key Format

PGP, or Pretty Good Privacy, is a proprietary encryption program used for signing, encrypting, and decrypting files and directories. PGP files are public key files, which are used in this process to authenticate repositories as valid sources within apt. GPG, or GNU Privacy Guard, is an open-source alternative to PGP. GPG files are usually keyrings, which are files that hold multiple keys. Both of these file types are commonly used to sign and encrypt data.

gpg is GPG’s command-line tool that can be used to authorize external repositories for use with apt. However, apt expects keys to be in a GPG keyring format (binary .gpg files). In order to use this command-line tool with ASCII-armored PGP files, you must convert them into this format.

Elasticsearch presents a common scenario for key conversion, and will be used as the example for this section. You’ll download a key formatted for PGP and convert it into an apt compatible format with a .gpg file extension. You’ll do this by running the gpg command with the --dearmor flag. Next, you’ll add the repository link to the list of package sources, while attaching a direct reference to your converted key. Finally, you will verify this process by installing the Elasticsearch package.

Projects that require adding repositories with key verification will always provide you with a public key and a repository URI representing its exact location. For our Elasticsearch example, the documentation gives these components on their installation page.

Here are the components given for Elasticsearch:

  • Key: https://artifacts.elastic.co/GPG-KEY-elasticsearch
  • Repository: https://artifacts.elastic.co/packages/9.x/apt stable main

Next, you have to determine whether you are given a PGP or GPG file to work with. You can inspect the key file by opening the URL with curl (learn more about using curl in our guide How To Download Files with curl):

  1. curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch

This will output the contents of the key file, which starts with the following:

-----BEGIN PGP PUBLIC KEY BLOCK-----
. . .

Despite having GPG in the URL, the first line indicates that this is actually a PGP key file. Take note of this, because apt expects keys to be stored in a GPG keyring format.

Originally, apt-key detected PGP files and converted them into GPG format automatically by calling gpg in the background. With apt-key deprecated, this conversion must now be handled manually using gpg --dearmor, which will be covered in the next step. For a deeper understanding of GPG and encryption, see How To Use GPG to Encrypt and Sign Messages.

Step 2 — Downloading the Key and Converting to an apt Compatible File Type

With the gpg method, you must always download the key before adding it to the list of package sources. Previously with apt-key, this ordering was not always enforced. Now, you are required to reference the path to the downloaded key file in your sources list. If you have not downloaded the key, you cannot reference an existing path.

With Elasticsearch you are working with a PGP file, so you will convert it to a GPG file format after download. The following example uses curl to download the key, with the download being piped into a gpg command. gpg is called with the --dearmor flag to convert the PGP key into a GPG keyring format, with -o used to indicate the file output.

On modern Ubuntu systems, the /etc/apt/keyrings directory is the recommended location for storing administrator-managed keyrings. Create this directory if it does not already exist:

  1. sudo mkdir -p /etc/apt/keyrings

Then download and convert the key:

  1. curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /etc/apt/keyrings/elastic-9.x.gpg

This converts the PGP file into the correct GPG format, making it ready to be added to the list of sources for apt.

Note: In older documentation, /usr/share/keyrings is often used for storing keyrings. While this still works, it is generally intended for keyrings managed by system packages. For manually added repositories, /etc/apt/keyrings is now the preferred location.

Note: If the downloaded file is already in a GPG keyring format, you can instead download the file directly to /etc/apt/keyrings without converting it:

  1. curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo tee /etc/apt/keyrings/elastic-9.x.gpg > /dev/null

In this case, the curl command’s output is piped into tee to save the file in the correct location.

Step 3 — Adding the Repository to Your List of Package Sources

With the key downloaded and in the correct GPG file format, you can add the repository to the apt package sources while explicitly linking it to the key you obtained. There are three methods to achieve this, all of which are related to how apt finds sources. apt pulls sources from a central sources.list file, .list files in the sources.list.d directory, and .sources files in the sources.list.d directory.

Though there is no functional difference between these options, using separate files in sources.list.d is generally easier to manage and maintain.

Option 1 — Adding to sources.list Directly

The first method involves inserting a line representing the source directly into /etc/apt/sources.list, the primary file containing apt sources. There are multiple sources in this file, including the default sources that come with Ubuntu. It is perfectly acceptable to edit this file directly, though Option 2 and Option 3 present more modular solutions that are easier to edit and maintain.

Open /etc/apt/sources.list with nano or your preferred text editor:

  1. sudo nano /etc/apt/sources.list

Then add the external repository to the bottom of the file:

deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/elastic-9.x.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main

This line contains the following information about the source:

  • deb: Specifies that the source uses a Debian package format
  • arch=amd64,arm64: Specifies the architectures the APT data will be downloaded for
  • signed-by=/etc/apt/keyrings/elastic-9.x.gpg: Specifies the key used to authorize this source. This is a required addition in modern APT usage and ensures that the key is only trusted for this repository
  • https://artifacts.elastic.co/packages/9.x/apt stable main: The URI representing the repository location

Save and exit by pressing CTRL+O, then CTRL+X.

Option 2 — Creating a New .list File in sources.list.d

With this option, you will instead create a new file in the sources.list.d directory. apt parses both this directory and sources.list for repository additions. This method allows you to isolate repository additions within separate files.

If you ever need to remove or modify this repository, you can edit or delete this file without affecting other entries in sources.list.

To do this, pipe an echo command into a tee command to create a new file and insert the appropriate line. The file is named elastic-9.x.list in the following example, but any unique filename will work:

  1. echo "deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/elastic-9.x.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-9.x.list > /dev/null

This command is equivalent to manually creating the file and inserting the same line of text.

Option 3 — Creating a .sources File in sources.list.d

The third method writes to a .sources file instead of a .list file. This method uses the deb822 multiline format, which is more structured and less ambiguous than the single-line deb format, while remaining functionally equivalent.

Create a new file:

  1. sudo nano /etc/apt/sources.list.d/elastic-9.x.sources

Then add the external repository using the deb822 format:

Types: deb
Architectures: amd64 arm64
Signed-By: /etc/apt/keyrings/elastic-9.x.gpg
URIs: https://artifacts.elastic.co/packages/9.x/apt
Suites: stable
Components: main

Save and exit after inserting the text.

This format organizes the same information as the one-line format, but in a clearer, field-based structure. One difference is that it uses spaces instead of commas when specifying multiple values (for example, amd64 arm64 instead of amd64,arm64).

Next, you will verify this process by performing a test installation.

Step 4 — Installing the Package from the External Repository

You must run apt update in order to prompt apt to read the main sources.list file, as well as all .list and .sources files in the sources.list.d directory. Running apt install without updating first may result in a failed installation or the installation of an outdated package from the default repositories.

Update your package lists:

  1. sudo apt update

Then install your package:

  1. sudo apt install elasticsearch

Nothing changes in this step compared to the apt-key method. Once this command completes, you will have successfully installed the package from the external repository.

Verifying the Repository Configuration

If the installation succeeds without errors, it confirms that:

  • The repository has been added correctly
  • The key is properly associated using the signed-by option
  • APT is able to authenticate packages from the repository

If you encounter errors (such as missing keys or signature verification issues), review the previous steps to ensure that:

  • The key file exists in /etc/apt/keyrings
  • The correct path is specified in the signed-by option
  • The repository entry is correctly formatted

Addendum — Adding an External Repository Using a Keyserver

This section will briefly go over using gpg with a keyserver instead of a public key to add an external repository. The process is nearly identical to the public key method, with the difference being how gpg is called.

add-apt-repository is the keyserver-based counterpart to apt-key, and both are deprecated. In this scenario, instead of a key file and repository URI, you are given a keyserver URL and a key ID. You can then download the key directly from the keyserver into a GPG keyring file without needing to convert it.

Using the open-source programming language R as an example, here are the given components, which can also be found in the installation instructions on the official project site:

  • Keyserver: keyserver.ubuntu.com
  • Key ID: E298A3A825C0D65DFD57CBB651716619E084DAB9
  • Repository: https://cloud.r-project.org/bin/linux/ubuntu noble-cran40/

First, download the key from the keyserver using gpg. Create the keyrings directory if it does not already exist:

  1. sudo mkdir -p /etc/apt/keyrings

Then run:

  1. sudo gpg --homedir /tmp --no-default-keyring --keyring /etc/apt/keyrings/R.gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9

This command includes the following flags, which differ from using gpg with a public key:

  • --no-default-keyring combined with --keyring allows outputting to a new file instead of importing into an existing keyring
  • --keyserver combined with --recv-keys specifies the keyserver and the key ID to retrieve
  • --homedir /tmp overrides the default location for temporary files. Without this, gpg may attempt to write to /root, which can cause permission issues

Note: Keyservers can sometimes be slow, unreliable, or blocked by network policies. When available, downloading keys directly over HTTPS (as shown in previous sections) is generally more reliable.

Next, add the repository to a .list file. This is done in the same manner as adding an external repository using a public key:

  1. echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/R.gpg] https://cloud.r-project.org/bin/linux/ubuntu noble-cran40/" \
  2. | sudo tee /etc/apt/sources.list.d/R.list > /dev/null

Then update your package lists:

  1. sudo apt update

Finally, install the package:

  1. sudo apt install r-base

Using gpg to add external repositories is similar whether you are working with public keys or keyservers, with the primary difference being how the key is retrieved.

Migrating from apt-key and Fixing Issues After Ubuntu 24.04 Upgrades

If your system was originally configured using apt-key, you may encounter warnings or repository errors after upgrading to Ubuntu 24.04 or later. This is because older Ubuntu versions stored repository signing keys in global keyrings, while newer versions of APT require keys to be explicitly associated with individual repositories.

On systems that used apt-key, keys are typically stored in:

/etc/apt/trusted.gpg

or in separate files within:

/etc/apt/trusted.gpg.d/

These keyrings were designed to hold trusted keys for all repositories on the system. While this approach was convenient, it allowed any trusted key to authenticate packages from any repository. As discussed earlier, this global trust model introduces security risks and has been deprecated in favor of a more restrictive approach.

Beginning with Ubuntu 24.04, APT enforces stricter handling of signing keys. Instead of relying on globally trusted keyrings, repositories are expected to declare their associated key using the signed-by option. When this association is missing, APT may raise warnings or fail to authenticate the repository.

Recognizing the Problem

After an upgrade, these issues typically surface when running:

  1. sudo apt update

You may see warnings indicating that a key is stored in a legacy keyring, or errors stating that a repository cannot be verified. For example, you may see a warning like the following:

Key is stored in legacy trusted.gpg keyring

Or you may see signature-related errors such as NO_PUBKEY if APT cannot determine which key to use, or if the repository’s signing key is missing.

In some cases, APT may skip the repository entirely, which can lead to missing packages, failed installations, or older package versions being installed from the default Ubuntu repositories.

These symptoms are not caused by a missing key, but rather by the way the key is stored and referenced. Even if the correct key exists on the system, APT requires it to be explicitly linked to the repository.

Migrating Keys to Scoped Keyrings

To resolve these issues, you need to migrate keys from the legacy global keyrings into dedicated keyring files and update your repository configuration accordingly.

If you have multiple third-party repositories configured, migrate one repository at a time. This makes it easier to verify that each repository still updates cleanly before moving on to the next.

Begin by listing all keys currently trusted by APT:

  1. apt-key list

Although apt-key is deprecated, it can still be used for inspection during migration. Review the output to identify the key associated with the repository you want to fix. Look for identifying details such as the key ID, fingerprint, or organization name.

Once you have identified the correct key, export it and convert it into a GPG keyring file. First, ensure that the keyrings directory exists:

  1. sudo mkdir -p /etc/apt/keyrings

Then export and convert the key:

  1. sudo apt-key export <KEY_ID> \
  2. | gpg --dearmor \
  3. | sudo tee /etc/apt/keyrings/<repo>.gpg > /dev/null

This command extracts the key from the legacy keyring, converts it into a binary .gpg format, and saves it in a dedicated keyring file. Using a descriptive filename helps you keep track of which key belongs to which repository.

Updating the Repository Configuration

After creating the keyring file, you must update the repository definition so that it explicitly references the new key.

Locate the repository entry in either /etc/apt/sources.list or a file under /etc/apt/sources.list.d/, and modify it to include the signed-by option:

deb [signed-by=/etc/apt/keyrings/<repo>.gpg] https://example.com stable main

If the repository is defined in a .sources file using the deb822 format, add or update the Signed-By: field to point to the same keyring file.

This step is essential. Without the signed-by option, APT will not associate the repository with the correct key, even if the key exists on the system.

Cleaning Up Legacy Keys

Once the repository is correctly configured and functioning, you can remove the key from the legacy keyring:

  1. sudo apt-key del <KEY_ID>

This ensures that the key is no longer trusted globally and cannot be used by other repositories. If multiple repository entries rely on the same key, update those entries first before removing it.

Verifying the Migration

After completing the migration, update your package lists:

  1. sudo apt update

If everything is configured correctly, the update process should complete without warnings about legacy keyrings. The repository should be fetched successfully, and you should be able to install packages without encountering signature verification errors.

If issues persist, double-check that the keyring file exists at the specified path and that the repository entry correctly references it.

Additional Considerations for Upgraded Systems

Systems that have been upgraded across multiple Ubuntu versions often accumulate legacy configurations over time. It is common for multiple repositories to rely on keys stored in global keyrings, so you may need to repeat this process for each affected repository.

You may also encounter third-party documentation that still uses apt-key. In such cases, adapt those instructions by downloading the key and converting it using gpg --dearmor, as shown earlier in this guide.

Taking the time to migrate these keys not only resolves warnings and restores repository functionality, but also ensures that your system follows modern APT security practices. By isolating trust to individual repositories, you reduce the risk of unintended or unauthorized package installation.

Replacing apt-key in Automation Workflows (Docker, Scripts, and Ansible)

In many automated environments, such as Docker builds, provisioning scripts, and configuration management workflows, repository keys were traditionally added using apt-key. A commonly used pattern looked like this:

  1. wget -qO - https://example.com/key.gpg | sudo apt-key add -

This approach was convenient because it allowed a key to be downloaded and trusted in a single step. However, it relied on the same global trust model discussed earlier, where any imported key was trusted system-wide. While this behavior simplified automation, it also introduced security risks and made it difficult to control which repositories a key was allowed to authenticate.

As apt-key has been deprecated and removed in newer Ubuntu releases, this pattern is no longer suitable for modern systems. In automated workflows, continuing to use it can lead to warnings, failed builds, or inconsistent behavior across different environments. Updating these workflows is therefore essential to ensure both compatibility and security.

Applying the Modern GPG Workflow in Automation

The modern approach mirrors the manual process described earlier in this guide. Instead of adding a key directly to a global keyring, you explicitly download the key, convert it into a GPG keyring file, and store it in /etc/apt/keyrings. The repository is then configured to use this key via the signed-by option.

Although the underlying steps are the same, automation introduces additional considerations, such as idempotency, reproducibility, and minimizing unnecessary operations.

In a Dockerfile, these steps are typically combined into a single RUN instruction. This ensures that the key is created, associated with the repository, and immediately used during the package index update, while also avoiding extra image layers. For more on working with Docker, see How To Install Docker on Ubuntu:

RUN mkdir -p /etc/apt/keyrings \
 && curl -fsSL https://example.com/key.gpg \
 | gpg --dearmor -o /etc/apt/keyrings/example.gpg \
 && echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com stable main" \
 > /etc/apt/sources.list.d/example.list \
 && apt-get update

This pattern ensures that the repository is fully configured within the same build step, reducing the likelihood of transient errors and improving build consistency.

In shell scripts, the same workflow is often written in a more explicit, step-by-step manner. This can improve readability and make debugging easier, especially when scripts are reused across different systems. For more on shell scripting, see An Introduction to Linux Basics:

  1. sudo mkdir -p /etc/apt/keyrings
  2. curl -fsSL https://example.com/key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg
  3. echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com stable main" | sudo tee /etc/apt/sources.list.d/example.list > /dev/null

By following the same structure as the manual process, these scripts remain easy to understand while still adhering to modern APT requirements.

Using Scoped Keyrings in Ansible

In configuration management tools such as Ansible, repository setup is often abstracted through modules. However, older playbooks may still rely on patterns that internally use apt-key, or assume that keys can be globally trusted. For more on Ansible, refer to How to Install and Configure Ansible on Ubuntu.

To align with current best practices, it is important to explicitly manage the lifecycle of the key. This involves ensuring that the keyrings directory exists, downloading the key, converting it into the correct format, and then referencing it when adding the repository.

For example:

- name: Ensure keyrings directory exists
  ansible.builtin.file:
    path: /etc/apt/keyrings
    state: directory
    mode: '0755'

- name: Download repository key
  ansible.builtin.get_url:
    url: https://example.com/key.gpg
    dest: /tmp/example.gpg

- name: Convert key to keyring format
  ansible.builtin.command:
    cmd: gpg --dearmor -o /etc/apt/keyrings/example.gpg /tmp/example.gpg

- name: Add repository
  ansible.builtin.apt_repository:
    repo: "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com stable main"

This approach ensures that the key is stored in a predictable location and that the repository explicitly references it, making the configuration both secure and maintainable.

Considerations for Reliable Automation

When adapting existing automation workflows, it is important to ensure that all steps—from key retrieval to repository configuration—are handled consistently. In particular, the keyring file must exist before the repository is added, since APT will attempt to validate the repository immediately during an update.

In containerized environments, grouping related commands into a single layer helps maintain efficiency and avoids unnecessary rebuilds. In scripts and configuration management tools, clarity and correctness are often more important, especially when the same logic is reused across multiple systems.

It is also important to ensure that the file path specified in the signed-by option exactly matches the location of the generated keyring file. Even small mismatches can lead to signature verification failures that may be difficult to diagnose in automated pipelines.

Why This Matters in Automated Environments

Automation amplifies configuration decisions. A deprecated command used in a single script can quickly propagate across multiple systems, images, or deployments. Over time, this can lead to widespread warnings, inconsistent behavior, or security weaknesses that are difficult to trace.

By updating your automation workflows to use scoped keyrings and the gpg --dearmor pattern, you ensure that your systems follow modern APT practices. This not only improves security by limiting trust between repositories, but also ensures compatibility with current and future Ubuntu releases.

Troubleshooting Common Errors

When configuring external repositories using GPG keyrings, you may encounter errors during apt update or while installing packages. These issues are usually caused by missing key associations, incorrect file paths, incorrect repository definitions, or legacy key configurations. This section outlines common symptoms, explains the most likely cause, and describes what to check and how to fix it.

NO_PUBKEY <KEY_ID>

This error indicates that APT cannot find a valid key to authenticate the repository.

This typically occurs when the key has not been properly converted into a keyring file, when the repository entry does not reference the key using the signed-by option, or when the keyring file does not exist at the specified path.

To resolve this issue, first confirm that the keyring file exists and that the repository definition points to the correct location.

If you store administrator-managed keyrings in /etc/apt/keyrings, you should ensure that the key file exists there and that the repository definition includes the exact signed-by path. If you are not sure which key APT is looking for, re-run sudo apt update and note the key ID shown in the NO_PUBKEY line.

If the key file is missing or was saved as an ASCII-armored key, recreate the keyring file using gpg --dearmor, then confirm that the signed-by path matches the actual filename and directory.

Legacy Keyring Warning

Key is stored in legacy trusted.gpg keyring

This warning appears when a key is still stored in a deprecated location such as /etc/apt/trusted.gpg or /etc/apt/trusted.gpg.d/.

Although the repository may still function, this configuration is no longer recommended and may lead to issues on newer Ubuntu releases.

To fix the warning, you should migrate the key into a dedicated keyring file (for example, under /etc/apt/keyrings) and update the repository definition to reference it using signed-by. Once you confirm that apt update succeeds for that repository, you can remove the old key from the legacy keyring to avoid leaving it trusted globally.

Repository Not Verified or Signature Errors

In some cases, APT may report that a repository is not signed or cannot be verified. This usually indicates a mismatch between the repository and the key being used.

This can happen if the wrong key was downloaded, if the keyring file is incomplete, if the repository URL or suite/component is incorrect, or if the repository definition references the wrong key.

To resolve the issue, confirm that the repository entry points to the intended repository URL and that the key fingerprint matches what the project publishes in its official documentation. If you are unsure whether the key file is correct, re-download the key from the official source and convert it again using gpg --dearmor.

Repository Not Being Used

There may be situations where apt update completes successfully, but packages do not appear to come from the external repository when you install them.

This is often caused by an incorrectly formatted repository entry, a repository file placed in the wrong location, or APT pinning and priority rules that prefer another source.

To troubleshoot this, ensure that the repository is defined either in /etc/apt/sources.list or in a file within /etc/apt/sources.list.d/. Then confirm that APT recognizes the repository and shows candidate versions for your package:

  1. apt policy

Permission Issues

Permission-related errors can occur if APT is unable to read the keyring file. This may happen if the file was created without sufficient privileges or if it has restrictive permissions.

To avoid this issue, ensure that commands writing to /etc/apt/keyrings are executed with sudo. You should also verify that the keyring file exists and is readable by APT. For most setups, a mode such as 0644 is sufficient for the keyring file. For more on Linux file permissions, see Linux Permissions Basics and How to Use Umask.

Keyserver Errors

When retrieving keys from a keyserver using gpg, you may encounter connection timeouts or failures. These issues are often caused by network restrictions or unreliable keyservers.

In such cases, it is recommended to use a secure keyserver such as hkps://keyserver.ubuntu.com, or to download the key directly over HTTPS when available. Direct downloads are generally more reliable in modern environments.

Final Checks

If issues persist, review the configuration systematically. You should confirm that the keyring file exists in /etc/apt/keyrings, that the repository entry includes the correct signed-by path, and that the repository definition is properly formatted. You should also confirm that the repository URL is correct and that the repository is reachable.

Once you make a change, re-run sudo apt update and verify that the warnings or errors no longer appear.

FAQs

1. Is apt-key deprecated in Ubuntu 22.04?

Yes, apt-key is deprecated in Ubuntu 22.04. Deprecation warnings began appearing in Ubuntu 20.10, and while apt-key may still function in Ubuntu 22.04, it is no longer recommended and has been removed entirely in Ubuntu 24.04 and later versions. The modern approach is to use gpg directly to manage repository keys and store them as scoped keyrings in /etc/apt/keyrings.

2. Is add-apt-repository deprecated?

Yes, add-apt-repository is also deprecated for the same reasons as apt-key. It relies on the same global trust model where keys are trusted system-wide rather than being scoped to individual repositories. The recommended alternative is to use gpg to retrieve keys from keyservers and associate them with specific repositories using the signed-by option.

3. How do I fix the “apt-key is deprecated” warning?

To fix the deprecation warning, you need to migrate your keys from the legacy global keyring to dedicated scoped keyring files. Follow these steps:

  1. Identify the key:

    1. apt-key list

    Look for the key ID or organization name that corresponds to the repository showing the warning.

  2. Create the keyrings directory and export the key:

    1. sudo mkdir -p /etc/apt/keyrings
    2. sudo apt-key export <KEY_ID> | gpg --dearmor | sudo tee /etc/apt/keyrings/<repo>.gpg > /dev/null

    This command extracts the key from the legacy keyring and saves it as a dedicated keyring file in /etc/apt/keyrings. Use a descriptive filename that clearly indicates which repository the key belongs to.

  3. Update the repository entry:

    Locate the repository in /etc/apt/sources.list or /etc/apt/sources.list.d/ and add the signed-by option:

    deb [signed-by=/etc/apt/keyrings/<repo>.gpg] https://example.com stable main
    

    This explicitly associates the key with its intended repository.

  4. Verify the configuration:

    1. sudo apt update

    If the update completes without warnings, the migration was successful.

  5. Remove the old key:

    1. sudo apt-key del <KEY_ID>

    This removes the key from the legacy keyring and completes the migration.

4. What is the difference between /etc/apt/trusted.gpg and /usr/share/keyrings/?

/etc/apt/trusted.gpg (and /etc/apt/trusted.gpg.d/) is the legacy location where apt-key stored globally trusted keys. Keys in these locations are trusted by APT for all repositories on the system, not just the repository they were intended for. This global trust model is now deprecated due to security concerns, as it violates the principle of least privilege and can allow compromised keys to authenticate packages from unrelated repositories.

/usr/share/keyrings/ is intended for keyrings that are managed by system packages installed through APT. When official packages need to provide their own signing keys, they typically place them in this directory. This location should generally not be modified manually by system administrators.

For manually added third-party repositories, the current best practice is to use /etc/apt/keyrings/, which is specifically designated for administrator-managed keyrings. Keys stored here should be explicitly associated with individual repositories using the signed-by option, ensuring that each key can only authenticate packages from its intended source. This directory must be created manually if it doesn’t exist on older Ubuntu installations.

5. What does gpg --dearmor do?

The gpg --dearmor command converts ASCII-armored PGP keys (which begin with -----BEGIN PGP PUBLIC KEY BLOCK-----) into binary GPG keyring format, which is what APT expects. This conversion is necessary because many repository keys are distributed as ASCII-armored files for readability and compatibility, but APT requires keys to be stored in binary .gpg keyring format for authentication.

6. Can I still use add-apt-repository on Ubuntu 22.04?

While add-apt-repository may still function on Ubuntu 22.04, it is not recommended because it uses the deprecated global trust model. The command has been deprecated alongside apt-key and should be replaced with the modern GPG workflow. Instead of using add-apt-repository, download keys from keyservers using gpg --recv-keys, convert them to keyring files, and manually configure the repository with the signed-by option.

7. How do I add an apt repository without add-apt-repository?

To add a repository without add-apt-repository, you need to manually retrieve the signing key from a keyserver and then create the repository configuration file with the appropriate signed-by option. Follow these steps:

  1. Create the keyrings directory:

    1. sudo mkdir -p /etc/apt/keyrings

    This ensures the directory exists for storing administrator-managed keyrings.

  2. Retrieve the key from the keyserver:

    1. sudo gpg --homedir /tmp --no-default-keyring --keyring /etc/apt/keyrings/<repo>.gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys <KEY_ID>

    This command downloads the key directly from the keyserver into a dedicated keyring file without adding it to the global keyring.

  3. Add the repository entry:

    1. echo "deb [signed-by=/etc/apt/keyrings/<repo>.gpg] https://example.com stable main" | sudo tee /etc/apt/sources.list.d/<repo>.list > /dev/null

    This creates a new .list file in /etc/apt/sources.list.d/. The signed-by option explicitly associates the key with this specific repository, ensuring it cannot be used to authenticate packages from other sources.

  4. Update package lists:

    1. sudo apt update

    This refreshes the package lists and verifies that the repository is accessible and properly authenticated. If the update completes without errors, the repository has been successfully configured.

8. Does the apt-key deprecation affect Ubuntu 20.04?

Ubuntu 20.04 itself does not show apt-key deprecation warnings, as these warnings began appearing in Ubuntu 20.10. However, if you upgrade from Ubuntu 20.04 to a newer version (such as Ubuntu 22.04 or 24.04), any repositories configured with apt-key will need to be migrated to use scoped keyrings. It’s also good practice to use the modern GPG workflow even on Ubuntu 20.04 to ensure compatibility when upgrading in the future.

Conclusion

In this tutorial, you learned how to replace apt-key and add-apt-repository with a modern GPG-based workflow for managing external repositories on Ubuntu. You covered how to download and convert keys into scoped keyrings, associate them with repositories using the signed-by option, and add repositories using both traditional and deb822 formats.

You also learned how to migrate legacy configurations, resolve issues after upgrading to Ubuntu 24.04, and adapt these practices for automation workflows such as Docker, shell scripts, and Ansible. With these techniques, you can securely manage APT repositories using methods that are compatible with current and future Ubuntu releases, and confidently adapt outdated installation instructions to follow modern best practices.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Manikandan Kurup
Manikandan Kurup
Editor
Senior Technical Content Engineer I
See author profile

With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.

Still looking for an answer?

Was this helpful?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Thank you. This is the clearest, concise yet adequately detailed explanation I’ve found on this topic.

Using gpg --recv-keys for PPAs directly won’t work in environments with controlled internet access. The actual route to get the ASCII armoured key is “https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x<fingerprint>” This can then be dearmoured and imported to the machine or docker builder which is running apt.

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.