apt "GPG error: NO_PUBKEY": add the key the right way, without apt-key
Fix apt "GPG error: The following signatures couldn't be verified: NO_PUBKEY": add the vendor's key to /etc/apt/keyrings with signed-by, and why apt-key is gone.
by OhSudo ··
Checked on real software: Ubuntu 24.04, apt · November 2026How we check
Err:3 https://download.docker.com/linux/ubuntu noble InRelease The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8W: GPG error: https://download.docker.com/linux/ubuntu noble InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8E: The repository 'https://download.docker.com/linux/ubuntu noble InRelease' is not signed.Each repository signs its packages, so that your machine can check they really come from there. apt has a repository in its list, and doesn’t have the key that verifies its signature.
The error gives you what you need: which repository, and which key. The fix is getting that key from the vendor and telling apt to use it for that one repository.
- Repositorysigns its package listssigned lists
- apt updatechecks the signaturekey missing(fails)
- NO_PUBKEYno key to verify it with(breaks here)
TL;DR
Using Docker as an example, with the address from the vendor’s install page:
sudo install -m 0755 -d /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpgsudo chmod a+r /etc/apt/keyrings/docker.gpgecho "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.listsudo apt update1. See which repository it is
The URL is in the error, and it’s what you need to identify. Find where it’s configured:
grep -rl 'download.docker.com' /etc/apt/sources.list /etc/apt/sources.list.d/Do you still need it? Removing a repository you no longer use is often the best fix:
sudo rm /etc/apt/sources.list.d/old-thing.listsudo apt update2. Get the key from the vendor
Look up the install instructions on the vendor’s own site, which give the key’s address. A key comes in one of two formats:
curl -fsSL https://example.com/key.asc -o /tmp/keyfile /tmp/keyfile says |
Format | What to do |
|---|---|---|
PGP public key block |
Text (“armored”) | Convert it with gpg --dearmor |
OpenPGP Public Key or PGP/GPG key public ring |
Binary | Copy it as it is |
Then check that it’s the key your error asked for:
gpg --show-keys --keyid-format long /tmp/keyThe output should contain 7EA0A9C3F273FCD8 or end with it. If it doesn’t, stop. You have the wrong key, or something’s wrong with the source.
3. Install it, for that repository only
sudo install -m 0755 -d /etc/apt/keyringssudo gpg --dearmor -o /etc/apt/keyrings/vendor.gpg /tmp/keysudo chmod a+r /etc/apt/keyrings/vendor.gpgThen point the repository’s line at it, in /etc/apt/sources.list.d/vendor.list:
deb [signed-by=/etc/apt/keyrings/vendor.gpg] https://example.com/apt stable mainOr in the newer format, in a .sources file:
Types: debURIs: https://example.com/aptSuites: stableComponents: mainSigned-By: /etc/apt/keyrings/vendor.gpgThen run sudo apt update.
signed-by is what makes this better than the old way, as this key is only trusted for this one repository.
4. Why not apt-key?
Old guides show this:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7EA0A9C3F273FCD8 # don'tapt-key is deprecated, and gone from recent Debian and Ubuntu releases, so you might see apt-key: command not found. It’s also how you get this warning on systems that still have it:
W: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.The problem is that a key in that shared keyring is trusted for every repository. A vendor’s key could then sign packages that look as though they come from Ubuntu. To move an old key to its own file:
sudo apt-key listsudo apt-key export 7EA0A9C3F273FCD8 | sudo gpg --dearmor -o /etc/apt/keyrings/vendor.gpgsudo apt-key del 7EA0A9C3F273FCD8Then add signed-by as in section 3.
5. Other causes
A PPA. add-apt-repository normally imports the key by itself. If it failed:
sudo add-apt-repository --remove ppa:name/heresudo add-apt-repository ppa:name/hereA vendor rotated its key. A key that worked last month now shows NO_PUBKEY or EXPKEYSIG. Download the new key from the vendor’s instructions, and overwrite your file.
An expired key. EXPKEYSIG means the key you have is past its date, and apt-key list or gpg --show-keys shows the date. Get the current one in the same way.
A clock that’s wrong. A machine with a date far in the past gets similar errors, including Release file … is not valid yet. Check timedatectl.
A corporate proxy that inspects traffic, and can return a page instead of the key. Run file /tmp/key to check what you downloaded. An HTML document isn’t a key.
The keys themselves. Ubuntu’s own archive key is in ubuntu-keyring, and Debian’s in debian-archive-keyring. If those are the ones missing, usually on an old release, reinstalling helps: sudo apt install --reinstall ubuntu-keyring.
6. In a Dockerfile
The commands are the same, and need curl and gnupg first, as images don’t have them. Keep it in a single RUN:
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl gnupg \ && install -m 0755 -d /etc/apt/keyrings \ && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpgA permission denied when reading that file usually means it wasn’t made readable with chmod a+r, since apt uses a separate user to read it.
Warning
Never use [trusted=yes], --allow-unauthenticated or --allow-insecure-repositories to get past this. They turn off the check that stops anyone on the network, or at the source, from feeding your server a fake package that runs as root. If you can’t get a key that matches, then don’t install from there.
Shell, we have a problem!
Similar, but different: E: Unable to locate package means the name isn’t in your list: see that article. The repository … does not have a Release file is usually an unsupported release, or a wrong URL. Temporary failure resolving is DNS. And on RHEL, the same thing is GPG check FAILED, solved with rpm --import and the vendor’s key.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.