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 _apt user (wrong permissions).

Solution#

  1. Find the source file for the failing repository:
grep -rn "download.docker.com" /etc/apt/sources.list /etc/apt/sources.list.d/
  1. Download the vendor's current key into /etc/apt/keyrings. Keys with an .asc extension 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
  1. 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.

  1. 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