You need to know why
apt-key add is deprecated
All of the answers so far work around the symptom ("Don't use
apt-key add") but fail to address the actual problem that led to
apt-key add being deprecated. The problem is not a question of appending a key to one big keyring file
etc/apt/trusted.gpg vs manually putting single-key keyring files into the directory
/etc/apt/trusted.gpg.d/. These two things are equivalent, and doing either one is a huge security risk.
The problem is that any key you add to either of the above is completely and unconditionally trusted by apt. This means that when installing any package from any repo (including the official distro repos), apt will happily accept the package being signed by any of those trusted keys (whether the key belongs to the repository the package is coming from or not). This weakens the assurance provided by the package signing mechanism against malicous packages being injected into the official Ubuntu mirrors network.
What we want to do instead is configure apt to accept signatures from a third-party repository only on packages being installed from that repository — no cross-signing. Apt's default pinning rules give higher priority to official distro repos, which (in conjunction with proper key management) offers some protection against third-party repos replacing distro-provided packages. (At least, I think that's default. You can use
apt-cache policy to inspect the current pin priorities, and if needed you can adjust pinning based on
origin to achieve this effect. See
man apt_preferences for details.)
The instructions given in Ugo Delle Donne's answer for converting the key to the (legacy) keyring v4 format that apt will accept are correct and helpful, but that's only half of the solution. I'll reiterate them here (cleaned up slightly) so all the steps are consolidated in one place:
- Download the key:
(No need for
wget defaults to saving the file in your current directory with the same filename it has on the server.)
- Verify that the filetype is "PGP public key block Public-Key (old)":
gpg supports a number of key formats, so if your key is in a different format, convert it by importing it into a temp keyring, then exporting it again:
gpg --no-default-keyring --keyring ./temp-keyring.gpg --import <keyfile>.<ext>
gpg --no-default-keyring --keyring ./temp-keyring.gpg --export --output <your-keyfile-name>.gpg
Now that you have your converted key, do not add it to
apt's trusted keystore by copying it into
/etc/apt/trusted.gpg.d/. Instead, put it somewhere like
/etc/apt/keyrings/. (You might need to create that
keyrings directory first.) There's nothing special about that location, it's just a convention recommended by
man 5 sources.list in Ubuntu 22.04 and a related Debian Wiki entry.
At this point, nothing has changed and
apt doesn't know the key exists. The last step is to modify the specific
.list file for the repository to tell apt where to find the key for that specific repo.
- Edit the file
/etc/apt/sources.list.d/<example>.list, and in between
deb and the url, add
Now apt will accept that key's signature for all packages in that repo and only that repo.
- If you already have keyring files in
/etc/apt/trusted.gpg.d/, you can
copy move them to
/etc/apt/keyrings/ as-is, and then update all the corresponding
.list files so each one has a
signed-by field pointing to its own key.
- If you already have keys in the
/etc/apt/trusted.gpg keyring file beyond the official repo keys, this answer details the steps to locate and remove them. You can then follow all the same steps above to set them up the safer way. (Exporting them from that keyring is also possible, but the exact steps are left as an exercise for the reader.)
- To import a repo's key from a keyserver to a standalone file:
gpg --no-default-keyring --keyring <output-file-name>.gpg --keyserver <some.keyserver.uri> --recv-keys <fingerprint>
- This should give you a key that apt will accept without conversion.
- Apt is still very trusting, and a malicious or compromised repo can bypass this measure easily because packages currently can run arbitrary shell code as root in their setup scripts. Closing off one attack vector doesn't hurt, though, and progress is (slowly) being made on other fronts.
- Optionally, you can switch to the newer, more verbose
Deb822 format using individual
.sources files instead of
.list files. It's more work, but personally I find the result far more readable.