The apt-key tool is deprecated as it stores all trusted keys in a single file, creating security risks. Modern systems require managing GPG keys individually in /etc/apt/trusted.gpg.d or /usr/share/keyrings with proper repository bindings.
When you add a GPG key using the deprecated apt-key command, the system displays a deprecation warning. This is because apt-key stores all trusted keys in a single /etc/apt/trusted.gpg file, which means any repository authenticated with that file can be cross-signed by unrelated GPG keys. This creates a security vulnerability where a compromised key could verify packages from any repository. Modern Debian and Ubuntu systems (including Ubuntu 24.04+) require managing keyring files individually in /etc/apt/trusted.gpg.d or /usr/share/keyrings. This approach binds specific GPG keys to specific repositories using the signed-by tag, preventing unauthorized package verification.
First, check what keys are currently stored in the legacy trusted.gpg file:
sudo apt-key listThis shows all keys with their IDs. Note the 8-character key ID at the end of each key fingerprint you need to migrate.
For each key you've added with apt-key, export it to the modern location. Replace KEYID with the 8-character ID from the previous step:
sudo apt-key export KEYID | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/keyname.gpg > /dev/nullThe --dearmor flag converts the ASCII-armored key format to binary format required by modern apt.
Example for a key with ID 12345678:
sudo apt-key export 12345678 | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/my-repo.gpg > /dev/nullFor new repositories, download the GPG key directly to the recommended location instead of using apt-key:
curl -sS https://example.com/repo-key.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/example-repo.gpg > /dev/nullYou can also use wget:
wget -qO - https://example.com/repo-key.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/example-repo.gpg > /dev/nullUpdate your repository source files to explicitly reference the key file using the signed-by tag. This binds the key to that specific repository, preventing cross-signing vulnerabilities.
For a repository list file at /etc/apt/sources.list.d/example-repo.list:
deb [signed-by=/etc/apt/trusted.gpg.d/example-repo.gpg] https://download.example.com/repository focal mainOr if storing keys in /usr/share/keyrings:
deb [signed-by=/usr/share/keyrings/example-repo.gpg] https://download.example.com/repository focal mainEdit existing sources.list entries and add the [signed-by=...] section right after 'deb'.
Test that the repository works with the new key:
sudo apt updateIf the update completes without warnings, remove the old key from the legacy trusted.gpg file. Replace KEYID with the key ID you exported:
sudo apt-key del KEYIDYou can verify the key was removed:
sudo apt-key listWhen choosing between /etc/apt/trusted.gpg.d and /usr/share/keyrings, the recommended approach is:
- Use /usr/share/keyrings for stable distribution-managed keyrings and package-provided keys
- Use /etc/apt/trusted.gpg.d for system administrator-added keys specific to the machine
On systems with SELinux enabled, ensure the key files have the correct security context. The gpg --dearmor conversion is important: the --dearmor flag converts from ASCII-armored format (with "-----BEGIN PGP PUBLIC KEY BLOCK-----" headers) to binary OpenPGP format that apt requires. Some newer versions of gpg use --dearmour (British spelling) - both are equivalent.
If you have many legacy keys from apt-key, consider using a script to batch export them all at once rather than manually processing each one.
E: Could not connect to proxy server
Could not connect to proxy server
E: Package 'package:i386' has no installation candidate
How to fix "Package package:i386 has no installation candidate" in apt
E: The value 'value' is invalid for APT::Default-Release
How to fix invalid APT::Default-Release value in APT
dpkg: error: unable to create new file 'path': Permission denied
How to fix dpkg permission denied errors in APT
subprocess installed post-removal script returned error exit status 1
How to fix "subprocess installed post-removal script returned error exit status 1" in APT