Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead
Asked Answered
E

11

152

I was installing elasticsearch following this guide, but elasticsearch is not really the part of this question.

In the first step, I need to add the key:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

and got the following message:

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).

The installation process was fine, but since it's deprecated, I'm looking for the new usage that replaces apt-key. (I have no problem installing the package.) From man apt-key I saw

apt-key(8) will last be available in Debian 11 and Ubuntu 22.04.

...

Binary keyring files intended to be used with any apt version should therefore always be created with gpg --export.

but it didn't say the alternative to apt-key add. I tried

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --export

but didn't work. So what do I use after the pipe of wget when apt-key is removed?

Elwandaelwee answered 31/8, 2021 at 4:14 Comment(1)
See thisScaliger
K
173

Adding a key to /etc/apt/trusted.gpg.d is insecure because it adds the key for all repositories. This is exactly why apt-key had to be deprecated.

Short version

Do similar to what Signal does. If you want to use the key at https://example.com/EXAMPLE.gpg for a repository listed in /etc/apt/sources.list.d/EXAMPLE.list, use:

sudo mkdir -m 0755 -p /etc/apt/keyrings/

curl -fsSL https://example.com/EXAMPLE.gpg |
    sudo gpg --dearmor -o /etc/apt/keyrings/EXAMPLE.gpg

echo "deb [signed-by=/etc/apt/keyrings/EXAMPLE.gpg] https://example.com/apt stable main" |
    sudo tee /etc/apt/sources.list.d/EXAMPLE.list > /dev/null
# Optional (you can find the email address / ID using `apt-key list`)
sudo apt-key del [email protected]
# Optional (not necessary on most systems)
sudo chmod 644 /etc/apt/keyrings/EXAMPLE.gpg
sudo chmod 644 /etc/apt/sources.list.d/EXAMPLE.list

Long version

While the deprecation notice recommends adding the key to /etc/apt/trusted.gpg.d, this is an insecure solution. To quote this article from Linux Uprising:

The reason for this change is that when adding an OpenPGP key that's used to sign an APT repository to /etc/apt/trusted.gpg or /etc/apt/trusted.gpg.d, the key is unconditionally trusted by APT on all other repositories configured on the system that don't have a signed-by (see below) option, even the official Debian / Ubuntu repositories. As a result, any unofficial APT repository which has its signing key added to /etc/apt/trusted.gpg or /etc/apt/trusted.gpg.d can replace any package on the system. So this change was made for security reasons (your security).

The proper solution is explained in that Linux Uprising article and on the Debian Wiki: Store the key in /etc/apt/keyrings/ (or /usr/share/keyrings/ if keys are managed by a package), and then reference the key in the apt source list.

Therefore, the appropriate method is as follows:

  1. Create directory
    Create the directory for PGP keys if it doesn't exist, and set its permissions. This step explicitly sets the recommended permissions, just in case you've changed your umask using sudo's umask_override. Creating the directory is actually only necessary in releases older than Debian 12 and Ubuntu 22.04, but it can't hurt to run this line either way.

    sudo mkdir -m 0755 -p /etc/apt/keyrings/
    
  2. Download key
    Download the key from https://example.com/EXAMPLE.gpg and store it in /etc/apt/keyrings/EXAMPLE.gpg. By giving options -fsSL to curl we enable error messages, ensure redirects are followed, and reduce output so you can see sudo's password prompt. The Debian wiki explains that you should dearmor the key (i.e. convert it from base64 to binary) for compatibility with older software.

    curl -fsSL https://example.com/EXAMPLE.gpg |
        sudo gpg --dearmor -o /etc/apt/keyrings/EXAMPLE.gpg
    

    Optionally, you can verify that the file you downloaded is indeed a PGP key by running file /etc/apt/keyrings/EXAMPLE.gpg and inspecting the output.

  3. Register repository
    A key has been added, but apt doesn't know about the repository yet. To add the repository, you should create a file in /etc/apt/sources.list.d/ that describes how to use the repository, and where to find the key. The contents of the created file should look something like this:

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

    The signed-by should link to the key you just downloaded.

    If a repository wants you to specify an arch, or you want to use multiple components (e.g. main contrib), the contents may instead be something like

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

    If you are adapting from an existing repo, just copy what they have, and add the signed-by=... between the [].

  4. (optional) Remove old key
    If you previously added a third-party key with apt-key, you should remove it. Run sudo apt-key list to list all the keys, and find the one that was previously added. Then, using the key's email address or fingerprint, run sudo apt-key del [email protected].

  5. (optional) Force-set permissions
    If you have a custom umask_override set for sudo, or if you use ACLs, files will be created with different permissions than usual. In those cases, explicitly set permissions for EXAMPLE.gpg and EXAMPLE.list to 644.

Using the newer DEB822 format

The newer DEB822 format for specifying apt repositories is much nicer and easier to use, but not yet fully supported by all tools across all platforms.

Short version

Instead of running the script mentioned above, run

echo "Types: deb
URIs: https://example.com/apt
Suites: stable
Components: main
Signed-By:
$(wget -O- https://example.com/EXAMPLE.gpg | sed -e 's/^$/./' -e 's/^/ /')" | sudo tee /etc/apt/sources.list.d/EXAMPLE.sources > /dev/null

# Optional (not necessary on most systems)
sudo chmod 644 /etc/apt/sources.list.d/EXAMPLE.sources

Long version

Instead of using the one-line format for sources in sources.list.d, you can also use the newer multi-line format, DEB822. This format is easier to read for humans and computers, and has been available in apt since 2015. Debian and Ubuntu plan to use DEB822 as the default format starting late 2023. Repolib's documentation has a nice comparison and covers the motivation behind the new format.. Additionally, apt 2.2.4 and newer support embedding the public key directly in the sources.list.

If you maintain a package hosted on a third-party repository, consider making an optional filled-in DEB822 .sources available to your users.

The reason this is currently a separate section in this answer instead of the main answer is that some still-supported versions of Debian and Ubuntu ship with old versions of apt. Specifically, Debian 10 LTS (EOL: 2024-06-30) and Ubuntu 20.04 (EOL: 2025-04-30) are too old, but Debian 11 and newer, and Ubuntu 22.04 and newer are good to go. Additionally, some tools that parse source files instead of wrapping around apt may not fully support all these features yet.

To switch from the one-line format to the DEB822 format, let's say you have the following two files:

  • /etc/apt/sources.list.d/example.list:
    deb [signed-by=/etc/apt/keyrings/EXAMPLE.gpg] https://example.com/apt stable main
    
  • /etc/apt/keyrings/EXAMPLE.gpg:
    (Real keys should be much longer than this. This one is too short to be secure.)
    -----BEGIN PGP PUBLIC KEY BLOCK-----
    
    mI0EZWiPbwEEANPyu6pUQEydxvf2uIsuuYOernFUsQdd8GjPE5yjlxP6pNhVlqNo
    0fjB6yk91pWsoALOLM+QoBp1guC9IL2iZe0k7ENJp6o7q4ahCjJ7V/kO89mCAQ09
    yHGNHRBfbCo++bcdjOwkeITj/1KjYAfQnzH5VbfmgPfdWF4KqS/TmJP9ABEBAAG0
    G0phbmUgRG9lIDxqYW5lQGV4YW1wbGUub3JnPojMBBMBCgA2FiEEK8v49DttJG7D
    35BwcvTpbeNfCTgFAmVoj28CGwMECwkIBwQVCgkIBRYCAwEAAh4BAheAAAoJEHL0
    6W3jXwk4YLID/0arCzBy9utS8Q8g6FDtWyJVyifIvdloCvI7hqH51ZJ+Zb7ZLwwY
    /p08+Xnp4Ia0iliwqSHlD7j6M8eBy/JJORdypRKqRIbe0JQMBEcAOHbu2UCUR1jp
    jJTUnMHI0QHWQEeEkzH25og6ii8urtVGv1R2af3Bxi9k4DJwzzXc5Zch
    =8hwj
    -----END PGP PUBLIC KEY BLOCK-----
    

Then you can replace these two files with the single file /etc/apt/sources.list.d/example.sources:

Types: deb
URIs: https://example.com/apt
Suites: stable
Components: main
Signed-By:
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 .
 mI0EZWiPbwEEANPyu6pUQEydxvf2uIsuuYOernFUsQdd8GjPE5yjlxP6pNhVlqNo
 0fjB6yk91pWsoALOLM+QoBp1guC9IL2iZe0k7ENJp6o7q4ahCjJ7V/kO89mCAQ09
 yHGNHRBfbCo++bcdjOwkeITj/1KjYAfQnzH5VbfmgPfdWF4KqS/TmJP9ABEBAAG0
 G0phbmUgRG9lIDxqYW5lQGV4YW1wbGUub3JnPojMBBMBCgA2FiEEK8v49DttJG7D
 35BwcvTpbeNfCTgFAmVoj28CGwMECwkIBwQVCgkIBRYCAwEAAh4BAheAAAoJEHL0
 6W3jXwk4YLID/0arCzBy9utS8Q8g6FDtWyJVyifIvdloCvI7hqH51ZJ+Zb7ZLwwY
 /p08+Xnp4Ia0iliwqSHlD7j6M8eBy/JJORdypRKqRIbe0JQMBEcAOHbu2UCUR1jp
 jJTUnMHI0QHWQEeEkzH25og6ii8urtVGv1R2af3Bxi9k4DJwzzXc5Zch
 =8hwj
 -----END PGP PUBLIC KEY BLOCK-----

Importantly, you must indent each line of the key block by (at least) one space, and you must put an indented . instead of an empty line. (Removing the empty line invalidates the key.) The script above does exactly that.

Finally, if you have a repo that specifies an exact path, such as

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

then your DEB822 must set Suites: deb/ (which must end with a /) and it must not have a Components: line.

Additional resources

Karynkaryo answered 7/3, 2022 at 16:16 Comment(14)
The Debian developer who deprecated apt-key WITHOUT replacing it with an equally user-friendly and quick command for this task, made NSA & FSB a HUGE favor...!Abidjan
NP, since I answered here I've come up with a complete automated process for myself, I shared it hereColeridge
/usr/share/keyrings is for package maintainers, use /etc/apt/keyrings. You can also check out this answer.Villasenor
@Abidjan What could be more user-friendly and quick than to just copy a file?Villasenor
@Villasenor it's not just a file copy, it additionally needs a file-edit to reference that new file, many opportunities for error, leading people to simply ignore warnings - unacceptable stance for such a sensitive issueAbidjan
@Abidjan What was really deprecated is not apt-key, but adding keys unconditionally trusted by apt. You could alternatively put the file into /etc/apt/trusted.gpg.d, and that was better than using apt-key add, because that way it was easier to see which keys were added, and generally a simpler operation. (FYI signed-by was supported (long?) before Debian Stretch.) So the difference really is the [signed-by=...] part. Which apt-key has nothing to do with...Villasenor
...For people who prefer to understand what they're doing, that's not a problem. For those who blindly follow the manuals... it's a matter of fixing the manual (example). Now, what exactly do you suggest? Make apt-key add add files to /etc/apt/keyrings (which is a breaking and rather unexpected change), provide a wrapper script that adds lines to sources.list, and fix the manuals?Villasenor
I follow the history of how things came to be, but from a user POV, the succinct apt-key CRUD CLI has been replaced by a loose set of recommendations, and just that.Abidjan
@Abidjan MX Linux has a "MX Fix GPG keys" that fixes it automatically. And MX Linux is the most popular Debian distro (maybe for reasons such as this)Philipson
This is great explanation, and it even fixes the Google Cloud SDK key, which is badly documented in the very own Google docs: cloud.google.com/sdk/docs/install The gpg --dearmor step was critical to make it work in Ubuntu 22.04. Thank you!Capitulate
For the key of PostgreSQL, I had to omit the dearmoring. Debian Bookworm.Median
@klausthorn Including dearmor for PostgreSQL works fine for me on a fresh install of Debian Bookworm. What goes wrong exactly if you include the dearmoring?Karynkaryo
How about automatically naming the file ? ThanksDenning
@Denning Good question. I don't think you can automatically name the .gpg file because you have to pass it through gpg --dearmor first, at which point the original filename is lost. I also skimmed the list of gpg's options, and it doesn't seem to have a way to dearmor a file in-place, so that's not an option either. You could maybe set a variable and substitute that (and remember to use quotes!), but I didn't describe that because different shells do that in different ways, and I want the code in my answer to be paste-able into all shells.Karynkaryo
C
20

!!Deprecated & insecure!!

answer found here : https://suay.site/?p=526

in short :

retrieve the key and add the key :

curl -s URL | sudo gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/NAME.gpg --import

authorize the user _apt :

sudo chown _apt /etc/apt/trusted.gpg.d/NAME.gpg
Carducci answered 1/9, 2021 at 14:9 Comment(5)
alternatively, instead of chown-ing, the referenced article suggests to update the file permissions from 600 to 644, just making the file readable for everyone, as it's a public key anyway: sudo chmod 644 /etc/apt/trusted.gpg.d/NAME.gpgFlashlight
You can avoid saving an additional file by: curl -s URL | sudo gpg .... Also, you can make the script copy-paste-able by parameterizing NAME.Elwandaelwee
This is insecure: The key will be trusted for all repositories, even your distro's own repositories. This is exactly why apt-key had to be deprecated. I have explained the method recommended by Debian and used by Signal in my answer.Karynkaryo
@IvanHanák Please be aware that while this answer works, it is recommended against by the Debian manual (amongst others), because it will trust that key for ALL repositories, not just the repository you're adding here.Karynkaryo
if curl fails can try wget -qO - URL | gpg ......Pentheus
B
7

As mentioned in current accepted answer, adding a key to /etc/apt/trusted.gpg.d is insecure because it adds the key for all repositories. This is why apt-key is giving this warning.

You can use a simpler solution like following:

curl -fsSL https://example.com/EXAMPLE.gpg | sudo gpg --dearmor -o /usr/share/keyrings/EXAMPLE.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/EXAMPLE.gpg] \
 https://example.com/apt stable main" \
| sudo tee -a /etc/apt/sources.list.d/EXAMPLE.list > /dev/null

sudo apt update
sudo apt install <package-name>
Beat answered 8/6, 2022 at 6:58 Comment(2)
Instead of sudo tee ... >/dev/null you can do sudo gpg --dearmor -o /usr/share/keyrings/EXAMPLE.gpg (with or without --yes for auto-overwrite). See my other response to a different answer.Coleridge
@Coleridge I have modified the solution as per your suggestion after testing it.Beat
O
3

From man apt-key (Ubuntu 22.04)

If your existing use of apt-key add looks like this:

wget -qO- https://myrepo.example/myrepo.asc | sudo apt-key add -

Then you can directly replace this with (though note the recommendation below):

wget -qO- https://myrepo.example/myrepo.asc | sudo tee /etc/apt/trusted.gpg.d/myrepo.asc

Osteoclast answered 12/4, 2023 at 13:41 Comment(1)
askubuntu.com/a/1307181/887635 explains in detail why your answer is insecure and should not be recommended.Manamanacle
P
2

MX Linux has a utility script called "MX Fix GPG keys" that takes care of this. Since it's just a bash script it most likely works fine with any other Debian based distro.

It's here https://github.com/MX-Linux/checkaptgpg

Philipson answered 27/11, 2022 at 14:10 Comment(1)
Haven't tried it but thanks for your sharing anyway.Elwandaelwee
P
1

I ran into the apt-key deprecation problem and warnings while adding the kubernetes-xenial repo using a gpg key available online. I was working in an Ubuntu 22.04.1 environment on Apple Silicon (M1/aarch64/arm64). The solution provided below is very similar to the one proposed by Vamsi Nerella elsewhere in this thread, but it includes an explicit example--along with the creation of a new keyring directory ('/etc/apt/keyrings').

This solution also avoids any use of the '/etc/apt/trusted.gpg.d' keyring directory, which some sources have said does nothing to remedy the problem that led to the deprecation of apt-key in the first place.

Although the packages added at the end of this example were from Kubernetes, this approach should work equally well with other packages, as Vamsi discussed.

This solution is also quite similar to the one proposed by Promise Preston (see thread), but it includes a reference to the system architecture, which I needed for my application. Perhaps others will benefit from this example.

Instead of this:

Create a 'kubernetes.list' file using a text editor such as vim or nano:

sudo vim /etc/apt/sources.list.d/kubernetes.list

Add the following text to the new file:

deb http://apt.kubernetes.io/ kubernetes-xenial main

Download the gpg key and use the deprecated apt-key to enable the use of the new repo:

sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
sudo apt-get update
sudo apt-get install kubeadm kubelet kubectl

Use this:

sudo mkdir -p /etc/apt/keyrings

sudo curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes.gpg
     
sudo echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/kubernetes.gpg] \
  http://apt.kubernetes.io/ kubernetes-xenial main" \
  | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null

sudo apt-get update
sudo apt-get install kubeadm kubelet kubectl

If you need a particular version of the Kubernetes packages, such as 1.26 (rather than the latest), you could do this in the last step:

sudo apt-get install -y kubelet=1.26.0-00 kubeadm=1.26.0-00 kubectl=1.26.0-00

As previously mentioned, you could substitute a different key for the one used in this example ('https://packages.cloud.google.com/apt/doc/apt-key.gpg'). The choice of 'kubernetes.gpg' in the dearmored key was arbitrary.

References:

Pieper answered 8/5, 2023 at 22:35 Comment(0)
B
0

I got his warning when trying to install nodejs and npm in Ubuntu 20.04

To be more precise:

Instead of this:

curl -sSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \

Use this:

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarn.gpg >/dev/null \
echo "deb [signed-by=/usr/share/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \

So the full installtion script looked like this:

apt-get install -y nodejs \
apt-get install -y npm gnupg2 \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarn.gpg >/dev/null \
echo "deb [signed-by=/usr/share/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \
Bashful answered 19/10, 2022 at 9:56 Comment(0)
S
0

Experienced this error recently while trying to install Jenkins on my EC2 instance. However, I was able to resolve it by following the steps below:

  1. Add a repository key to your system by running:

"wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key |sudo gpg --dearmor -o /usr/share/keyrings/jenkins.gpg"

You may have to replace jenkins with the package/software you want to install.

  1. Attach the Debian package repo address to the server's sources.list by running:

"sudo sh -c 'echo deb [signed-by=/usr/share/keyrings/jenkins.gpg] http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'"

  1. Run:

"apt update"

So apt will use the newly created repo.

  1. Go on to attempt/reattempt your installation.

Hope this helps :). Source: https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-22-04

Sixtasixteen answered 5/2, 2023 at 21:58 Comment(1)
Thank you for your sharing! It'd be greater to format the commands in two ` for a nicer format.Elwandaelwee
E
0

Another sample snippet, resolving the issue using updated deb822 format:

{ echo 'Types: deb'
  echo 'URIs: https://dl.k6.io/deb'
  echo 'Suites: stable'
  echo 'Components: main'
  echo 'Signed-By:'
  set -eo pipefail
  KEY=C5AD17C747E3415A3642D57D77C6C491D6AC1D69
  curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x$KEY" \
    | sed -e 's/^$/./g;s/^/ /g' 
} | sudo tee /etc/apt/sources.list.d/k6.sources

sudo apt-get update && sudo apt-get install k6

In this case, I'm installing k6.io CLI on Ubuntu 22.04 LTS. Adapt as you see fit.

Notice the .sources — not .list!

The benefit of deb822 is that the package-signing pubkey gets put inline in the sources-file (and validates only this repo's packages — which is more secure than trusting it with all other repos).
Being inline in the file saves another | sudo tee hoop:

Types: deb
URIs: https://dl.k6.io/deb
Suites: stable
Components: main
Signed-By:
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: Hockeypuck 2.1.0-189-g15ebf24
 Comment: Hostname: 
 .
 xsFNBGBLRGQBEADCqEcl4YKYLAW8p/rEzBrDLi8fewyqPTLFWosWeu1a4fKzPcW8
 ggl/pjRcXxAxgCt1EhX9bjOrzavdnfnKLYuNkwR0vLWZtNEhAsOovsDzFF6n+WsN
 jtxL9nBZZ/7tgImxMUds8EXotx3R0Le5kbW0QWaWK8NDNayUChGF4ijM1dcacefA
 1ObrQvEKMybdFMxQM+oQjLeIe8TARaoATeLXh/LprNHqDWSAqE3KogChAMykp10i
...

Had to whip up the above, because their official instructions got broken yet again.

Erlene answered 9/2, 2023 at 12:29 Comment(0)
L
0

Fast way to fix this for Linux users with a UI:

  1. Search for the PPA and do sudo add-apt-repository ppa:[MY_PPA] (the new PPA with keyring is added automatically and up to date)

  2. sudo apt update

  3. Navigate to "Software Sources -> PPA" and delete the old PPA (make sure the new one(s) has/have been added correctly with keyring)

Software Sources

Limey answered 11/4, 2023 at 16:23 Comment(0)
M
-4

This also happens for a poor connection, merely a connection impossible through the port used for download, and to be specific: port 80.

sudo ufw allow port 80

then retry, this can, for some, help.

Mercurial answered 21/4, 2023 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.