Linux Error: NO_PUBKEY / the following signatures couldn't be verified — Cause, Fix, and Troubleshooting Guide
How to fix the Linux apt 'NO_PUBKEY' and 'the following signatures couldn't be verified' error on Ubuntu using the modern signed-by keyring in /etc/apt/keyrings.
- #linux
- #troubleshooting
- #ubuntu
- #apt
- #security
Summary
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY <KEYID> means apt downloaded a repository’s signed Release file but does not have the GPG public key to verify it. On Debian/Ubuntu this is a trust problem, not corruption — apt is correctly refusing to trust an unverifiable repo. The modern, secure fix is to fetch the repository’s key into /etc/apt/keyrings/ and reference it with signed-by= in the source entry, not the deprecated apt-key.
Common Symptoms
apt-get updatewarns:W: GPG error: ... NO_PUBKEY 1234ABCD5678EF90.E: The repository '...' is not signed.the following signatures couldn't be verified because the public key is not available.- The affected repo’s packages become uninstallable or untrusted.
- Common right after adding a third-party repo (Docker, Kubernetes, NodeSource, HashiCorp).
Most Likely Causes of the ‘NO_PUBKEY / the following signatures couldn’t be verified’ Error
The most common production cause is adding a third-party apt repository without importing its signing key first. Other causes:
- A repo signing key rotated/expired and the new key was never installed.
- A key was installed under the deprecated
apt-key/trusted.gpg path that newer apt no longer reads for asigned-bysource. - A key file placed in
/etc/apt/keyringsin the wrong format (ASCII-armored where binary is expected, or vice versa). - The
debsource line lacks asigned-by=pointer to the keyring.
Quick Triage
# Which key ID is missing?
sudo apt-get update 2>&1 | grep -Eo 'NO_PUBKEY [0-9A-F]+'
# Which source is unsigned?
grep -R "" /etc/apt/sources.list /etc/apt/sources.list.d/
# Do you already have a keyrings directory?
ls -l /etc/apt/keyrings/ 2>/dev/null
Diagnostic Commands
# Extract the exact missing key IDs from the update output
sudo apt-get update 2>&1 | grep -Eo 'NO_PUBKEY [0-9A-F]{8,}'
# Inspect the offending source and confirm whether it uses signed-by=
grep -R "signed-by" /etc/apt/sources.list.d/
# List keys apt currently trusts (legacy + per-repo keyrings)
apt-key list 2>/dev/null # deprecated, read-only inspection
ls -l /etc/apt/keyrings/ /usr/share/keyrings/
# Inspect a keyring file's contents/format
gpg --show-keys /etc/apt/keyrings/<vendor>.gpg
Note the full key ID (or better, the vendor’s documented key URL) — you will fetch that specific key next.
Fix / Remediation
-
Fetch the key into
/etc/apt/keyringsand wire it withsigned-by(recommended, modern approach):sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.example.com/repo.gpg \ | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg sudo chmod a+r /etc/apt/keyrings/example.gpgThen reference it in the source (create/edit
/etc/apt/sources.list.d/example.list):echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://download.example.com/apt stable main" \ | sudo tee /etc/apt/sources.list.d/example.list sudo apt-get update -
If the vendor only publishes a key ID, pull it from a keyserver into a dedicated keyring (not the global trust store):
sudo gpg --no-default-keyring --keyring /etc/apt/keyrings/example.gpg \ --keyserver keyserver.ubuntu.com --recv-keys <KEYID> -
Point the source at that keyring with
signed-by=/etc/apt/keyrings/example.gpg, thenapt-get update. -
For a rotated key, install the new key file the same way and remove the stale one from
/etc/apt/keyringsor/usr/share/keyrings.
Warning: Do not use
apt-key add— it is deprecated and adds keys to a global trust store that applies to every repository, which is a security risk. Always scope keys per repository withsigned-by=and a dedicated file in/etc/apt/keyrings/.
Validation
# Update should now complete with no GPG/NO_PUBKEY warnings
sudo apt-get update
sudo apt-get update 2>&1 | grep -i 'NO_PUBKEY\|not signed' || echo "OK: repo verified"
# Confirm the source is bound to a keyring
grep -R "signed-by" /etc/apt/sources.list.d/<file>.list
# Packages from the repo now install as trusted
apt-cache policy <pkg-from-that-repo>
Prevention
- Always import a repo’s signing key into
/etc/apt/keyringsand bind it withsigned-by=when adding the source. - One keyring file per vendor — never share a global trusted keyring across repos.
- Track key expiry/rotation for third-party repos and update keys before they lapse.
- Keep system time correct (NTP); a wrong clock makes valid signatures appear expired/not-yet-valid.
- On RHEL/Rocky/Alma the analog is importing the repo GPG key with
rpm --import <url>and settinggpgcheck=1in the.repofile; the trust model (per-repo keys, verify before install) is the same.
Related Errors
- Hash Sum mismatch
- Failed to download metadata for repo
- The following packages have unmet dependencies
- Temporary failure in name resolution
Final Notes
NO_PUBKEY is apt doing its job: refusing to trust a repo it cannot verify. Fix it the modern way — a per-repo key in /etc/apt/keyrings bound with signed-by= — and leave apt-key behind. Keep the clock correct and track key rotations so trusted repos stay trusted.
Want faster Linux incident response? Use DevOps AI Toolkit to turn production errors into clear diagnostics, remediation steps, and reusable runbooks.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.