Issue#
Running apt update fails for a third-party repository (Docker, Kubernetes, PostgreSQL, etc.), and no packages from it can be installed or upgraded:
W: GPG error: https://download.docker.com/linux/debian bookworm InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/debian bookworm InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
Cause#
The repository's InRelease file is signed with a key that apt can't find. This usually happens because:
- The key was never added, or it was added with the deprecated
apt-key, which newer Debian/Ubuntu releases no longer use. - The source line has
signed-by=pointing to a missing or wrong keyring file. - The vendor rotated its signing key, so the key you have is outdated.
- The keyring file can't be read by the
_aptuser (wrong permissions).
Solution#
- Find the source file for the failing repository:
grep -rn "download.docker.com" /etc/apt/sources.list /etc/apt/sources.list.d/
- Download the vendor's current key into
/etc/apt/keyrings. Keys with an.ascextension can stay ASCII-armored:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
If a tool requires a binary keyring (.gpg), dearmor the key instead:
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- Point the repository at that key with
signed-by, replacing the old line:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
Remove any other entries for the same repository, for example a leftover docker.sources file. Duplicate entries with different signed-by values cause a Conflicting values set for option Signed-By error.
- If the vendor has no key URL, fetch the key by its ID from a keyserver:
KEYID=7EA0A9C3F273FCD8
sudo gpg --no-default-keyring --keyring /tmp/repo.gpg \
--keyserver hkps://keyserver.ubuntu.com --recv-keys "$KEYID"
sudo gpg --no-default-keyring --keyring /tmp/repo.gpg --export \
| sudo tee /etc/apt/keyrings/repo.gpg > /dev/null
sudo chmod a+r /etc/apt/keyrings/repo.gpg
Tip: Don't fix this with
[trusted=yes]. That turns off signature checking for the repository completely.
Verify#
Check that the keyring contains the key ID from the error (the last 16 hex digits of the fingerprint):
gpg --show-keys /etc/apt/keyrings/docker.asc
Then update again. The repository should load with no NO_PUBKEY or not signed messages:
sudo apt update
apt-cache policy docker-ce