恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
解决Ubuntu/Debian中apt update GPG签名验证失败(NO_PUBKEY)的完整指南
首页
资讯中心
/
解决Ubuntu/Debian中apt update GPG签名验证失败(NO_PUBKEY)的完整指南
解决Ubuntu/Debian中apt update GPG签名验证失败(NO_PUBKEY)的完整指南
发布时间:2026/8/14 6:24:52
1. 问题概述当apt update开始“抱怨”签名如果你在 Ubuntu 或基于 Debian 的 Linux 发行版上工作那么sudo apt update这条命令几乎是你日常操作的一部分。它负责从你配置的软件源Repository服务器上获取最新的软件包列表信息确保你后续的apt install或apt upgrade能知道有哪些新版本可用。然而某一天当你像往常一样执行这条命令时终端里却弹出了一段令人不安的红色错误信息核心内容通常是W: GPG error: http://example.com/ubuntu jammy InRelease: The following signatures couldnt be verified because the public key is not available: NO_PUBKEY XXXXXXXXXXXXXXXX E: The repository http://example.com/ubuntu jammy InRelease is not signed.或者更简洁的版本W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: ... NO_PUBKEY ...这个错误的本质是GPGGNU Privacy Guard签名验证失败。Linux 软件源为了确保安全防止软件包在传输过程中被篡改或服务器被劫持后提供恶意软件会对发布的软件包索引文件如InRelease或Release.gpg文件进行数字签名。你的系统apt工具在下载这些索引后会用对应的公钥去验证签名。如果系统里没有存储这个软件源对应的公钥或者公钥过期、不匹配验证就会失败apt出于安全考虑会拒绝使用这个“不可信”的软件源列表。简单来说这就像你收到一封声称来自银行的信但没有银行的官方印章签名或者你根本没有这个银行的印章样本公钥来核对你自然不敢相信信里的内容。apt也是一样它非常“固执”地要求所有软件来源都必须可验证。这个问题非常普遍尤其是在你手动添加了第三方软件源PPA、某些特定软件的官方源或者系统长期未更新导致密钥环keyring中的公钥过期时。接下来我们就深入拆解这个问题从原理到实操一步步把它解决掉。2. 核心原理APT、GPG与软件源安全机制要彻底解决“NO_PUBKEY”错误不能只停留在复制粘贴命令的层面理解其背后的工作原理能让你在未来遇到类似问题时举一反三。2.1 APT 更新流程与签名验证当你执行sudo apt update时背后发生了一系列事情读取源列表APT 首先读取/etc/apt/sources.list文件以及/etc/apt/sources.list.d/目录下的所有.list文件。这些文件里记录了一个个软件源的地址也就是告诉 APT 该去哪些服务器找软件。获取索引文件APT 会访问这些地址下载名为InRelease或Release加Release.gpg的文件。这些文件包含了该软件源中所有可用软件包的元信息列表如包名、版本、依赖关系、哈希值等。签名验证这是关键一步。InRelease文件本身内嵌了 GPG 签名而Release文件则有一个单独的Release.gpg签名文件。APT 会使用本地密钥环通常位于/etc/apt/trusted.gpg.d/和/usr/share/keyrings/中对应的公钥去验证这个签名是否有效。验证成功说明索引文件确实来自可信的软件源维护者且未被篡改。APT 会接受这个索引并将其与本地缓存合并。验证失败NO_PUBKEY说明本地没有可用于验证签名的公钥。APT 会抛出警告W或错误E并忽略从这个源获取的更新信息。这意味着你无法从这个源安装或更新任何软件包。更新本地缓存所有通过验证的源其索引信息会被下载并更新到本地的/var/lib/apt/lists/目录下供apt install等命令查询。2.2 公钥、私钥与信任链这里涉及非对称加密的基本概念私钥 (Private Key)由软件源的维护者秘密持有。他们用私钥对软件索引文件生成一个唯一的数字签名。私钥绝不能泄露。公钥 (Public Key)由软件源维护者公开分发。任何人都可以用它来验证签名是否由对应的私钥生成。公钥本身不需要保密。信任当你将某个公钥添加到系统的可信密钥环/etc/apt/trusted.gpg或相关目录时你就是在告诉系统“我信任用这个公钥验证过的所有内容”。这建立了一条从你系统管理员到软件源维护者的信任链。Ubuntu 和 Debian 官方源的公钥在系统安装时就已经预置了。问题出在第三方源上。当你通过add-apt-repository或手动添加.list文件时通常需要手动或自动导入对应的公钥。如果这一步失败或遗漏就会导致NO_PUBKEY错误。2.3 密钥环的演进apt-key的弃用与现状这是一个非常重要的实操背景知识。在较旧的教程或指南中你可能会看到使用apt-key add命令来导入密钥。但在现代 Ubuntu 版本大约 22.04 及以后中apt-key命令已被标记为弃用deprecated。为什么因为apt-key会将公钥添加到全局的、系统级的信任密钥环/etc/apt/trusted.gpg。这存在安全风险一个被入侵的第三方软件源密钥可能会被用来签署其他官方源的索引理论上造成信任污染。现代推荐的做法是“源列表绑定密钥”sources.list keyring将第三方源的公钥以文件形式通常为.asc或.gpg后缀下载到/etc/apt/keyrings/或/usr/share/keyrings/目录。在对应的.list源文件中通过signed-by参数明确指定该源使用哪个密钥文件进行验证。这种方式将密钥的信任范围限定在了特定的软件源实现了更精细化的安全管理。后文的解决方案会同时涵盖传统方法和现代最佳实践。3. 问题诊断定位缺失的公钥在动手修复之前先精确锁定问题源头。错误信息本身已经给出了关键线索。3.1 解读错误信息仔细看错误输出它通常包含两部分出错的软件源地址例如http://ppa.launchpad.net/someone/ppa/ubuntu。这告诉你哪个源出了问题。缺失的公钥 ID例如NO_PUBKEY 689A3B1B4C7438B2。后面那串 16 位十六进制数字或有时是 8 位短 ID就是缺失的公钥标识符。你的所有修复操作都将围绕这个源地址和这个密钥 ID展开。3.2 检查现有密钥你可以查看系统当前已经信任了哪些密钥以确认缺失的密钥是否真的不存在或者以另一种形式存在。列出所有受信任的密钥sudo apt-key list注意虽然apt-key管理已弃用但list子命令仍可用于查看。输出会显示密钥指纹fingerprint、UID所有者等信息。你可以对照错误中的密钥 ID通常是长指纹的后16位进行查找。查看现代密钥环目录ls -la /etc/apt/keyrings/ /usr/share/keyrings/ 2/dev/null查看这些目录下是否有相关的.gpg或.asc文件。3.3 检查源列表配置找到是哪个源文件引入了这个有问题的源。grep -r example.com /etc/apt/sources.list /etc/apt/sources.list.d/ --include*.list将example.com替换为错误信息中的域名部分。这能帮你定位到具体的.list配置文件方便后续修改。4. 解决方案大全从获取公钥到彻底修复根据不同的情况有几种方法可以解决NO_PUBKEY错误。我将从最常见、最推荐的方法开始介绍。4.1 方法一使用apt-key add传统方法适用于旧系统或应急尽管不推荐但在某些尚未升级管理方式的系统或者你需要快速解决问题的场景下这可能仍是有效途径。关键在于找到正确的公钥。步骤1获取公钥你需要使用缺失的密钥 ID例如689A3B1B4C7438B2去密钥服务器上下载它。最常用的密钥服务器是keyserver.ubuntu.com。sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 689A3B1B4C7438B2--keyserver: 指定密钥服务器。--recv-keys: 后面跟上缺失的密钥 ID。执行过程解析这条命令会连接指定的密钥服务器搜索 ID 为689A3B1B4C7438B2的公钥并将其下载并添加到系统的全局可信密钥环/etc/apt/trusted.gpg中。步骤2验证与更新添加成功后再次运行更新命令错误应该消失。sudo apt update实操心得与注意事项密钥服务器可能无响应如果keyserver.ubuntu.com连接慢或失败可以尝试其他服务器如hkp://keyserver.ubuntu.com:80或pgp.mit.edu。使用短密钥 ID有时错误信息或网上教程给出的是 8 位短 ID如4C7438B2。你可以尝试用短 ID 下载但长 ID 冲突概率更低更推荐。apt-key的警告执行命令时可能会看到警告Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8))。请务必留意这意味着系统鼓励你采用更安全的方法即方法二。并非万能有些第三方源并不将密钥上传到公共密钥服务器而是通过其他方式分发如在其官网提供.asc文件下载。此时这个方法会失败。4.2 方法二现代最佳实践 - 下载密钥文件并绑定源这是当前 Ubuntu/Debian 社区推荐的安全做法。我们将公钥作为一个独立的文件管理并让特定的软件源显式地使用它。步骤1创建密钥环目录如果不存在sudo mkdir -p /etc/apt/keyrings步骤2下载公钥文件你需要知道公钥文件的下载地址。这通常可以在软件源的官方安装指南中找到。场景A从密钥服务器下载为文件sudo gpg --homedir /tmp --no-default-keyring --keyring /etc/apt/keyrings/myrepo.gpg --keyserver keyserver.ubuntu.com --recv-keys 689A3B1B4C7438B2--homedir /tmp 指定一个临时目录存放 GPG 的临时文件避免污染用户密钥环。--no-default-keyring 不使用默认密钥环。--keyring 指定将密钥保存到哪个文件/etc/apt/keyrings/myrepo.gpg。最后的--recv-keys参数和密钥 ID 与之前相同。执行成功后密钥就保存在/etc/apt/keyrings/myrepo.gpg文件里了。场景B直接下载提供的.asc或.gpg文件很多项目官网会直接提供一个密钥文件的下载链接。例如Docker 的 GPG 密钥sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc或者使用wgetsudo wget -O /etc/apt/keyrings/docker.asc https://download.docker.com/linux/ubuntu/gpg注意下载后最好确认一下文件类型有时.asc(ASCII 格式) 和.gpg(二进制格式) 都可以但源文件配置中后缀要一致。步骤3修改软件源列表文件绑定密钥找到该软件源对应的.list文件位于/etc/apt/sources.list.d/或直接编辑/etc/apt/sources.list。修改其格式添加[signed-by/path/to/keyfile]选项。修改前传统格式deb http://ppa.launchpad.net/someone/ppa/ubuntu jammy main修改后现代格式deb [signed-by/etc/apt/keyrings/myrepo.gpg] http://ppa.launchpad.net/someone/ppa/ubuntu jammy main或者如果密钥文件是.asc格式deb [signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu jammy stable步骤4更新并验证sudo apt update此时APT 会使用你指定的密钥文件来验证该源的签名错误应被解决。核心技巧与深度解析signed-by路径必须绝对正确这是最容易出错的地方。确保路径指向你刚刚下载或创建的密钥文件并且文件名和扩展名完全匹配。可以使用ls -l /etc/apt/keyrings/仔细核对。一个密钥文件可用于多个源如果同一个组织维护了多个软件源比如 Docker 有 stable, test, nightly 频道它们可能使用同一个签名密钥。你只需要下载一次密钥然后在多个deb行中都使用[signed-by/same/path/to/key.gpg]即可。文件权限确保密钥文件对 root 用户可读即可通常644权限是合适的。为什么更安全这种方式将信任关系“锚定”在具体的源和密钥文件上。即使这个密钥被用于签署其他恶意源只要你的其他源列表没有引用这个密钥文件就不会受到影响。同时删除一个软件源时连同其密钥文件一起删除清理更彻底。4.3 方法三针对 Launchpad PPA 的特殊情况Launchpad 是 Ubuntu 最常用的第三方软件源托管平台。对于 PPAPersonal Package Archive通常有更简单的处理方法因为add-apt-repository命令会自动处理密钥。情况1你刚刚添加 PPA 就报错这可能是因为网络问题导致添加 PPA 时自动导入密钥失败。可以尝试重新添加sudo add-apt-repository --remove ppa:someuser/somerepo # 先移除 sudo add-apt-repository ppa:someuser/somerepo # 再添加第二次添加时add-apt-repository会再次尝试从 Launchpad 获取并导入密钥。情况2已添加的 PPA 突然报错密钥轮换PPA 维护者可能会更新他们的签名密钥。此时旧密钥失效新密钥未导入。解决方法同样是更新 PPAsudo add-apt-repository --update ppa:someuser/somerepo--update参数会刷新该 PPA 的信息包括获取新的公钥。情况3手动处理 PPA 密钥如果你想用方法二的“现代方式”管理 PPA 密钥可以手动操作。PPA 的密钥通常可以通过这个 URL 模式获取https://keyserver.ubuntu.com/pks/lookup?opgetsearch0x[KEY_ID]。但更简单的方法是观察add-apt-repository命令在/etc/apt/trusted.gpg.d/目录下生成的.gpg文件然后将其移动到/etc/apt/keyrings/并修改源文件。不过对于 PPA使用系统工具add-apt-repository仍然是最高效、兼容性最好的方式。4.4 方法四终极方案——更新整个系统的密钥环有时报错的不是第三方源而是 Ubuntu 官方源本身。这通常是因为系统安装镜像较旧或者长期未更新导致预置的官方密钥已过期或被新的密钥取代。更新ubuntu-keyring和debian-keyring包sudo apt update # 可能部分源还能用 sudo apt install --reinstall ubuntu-keyring debian-keyring这两个包包含了 Ubuntu 和 Debian 官方软件源的当前可信公钥集合。重新安装它们可以刷新系统中的官方密钥。更新ca-certificates虽然与 GPG 密钥直接关系不大但更新 CA 证书库有助于解决因 HTTPS 证书问题导致的源连接失败有时会与密钥错误同时出现。sudo apt install --reinstall ca-certificates完成上述操作后再次运行sudo apt update官方源的密钥错误通常会被修复。5. 疑难杂症与深度排查即使按照上述方法操作你可能还是会遇到一些棘手的情况。下面是一些常见疑难问题的排查思路。5.1 密钥服务器连接超时或失败当你使用apt-key adv或gpg --recv-keys时可能会遇到gpg: keyserver receive failed: No data或长时间无响应。解决方案更换密钥服务器除了keyserver.ubuntu.com还可以尝试hkp://keyserver.ubuntu.com:80(指定端口和协议)pgp.mit.edukeys.openpgp.orgkeyserver.ubuntu.com的 IPv4 地址有时 DNS 解析有问题使用hkp://协议gpg默认可能使用hkps://(加密的 HKP)在某些网络环境下可能被阻。强制使用hkp://sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys KEY_ID手动下载密钥文件如果服务器始终无法访问尝试在能正常上网的机器上通过浏览器访问https://keyserver.ubuntu.com/pks/lookup?opgetsearch0x[KEY_ID]将页面内容以-----BEGIN PGP PUBLIC KEY BLOCK-----开头保存为.asc文件然后通过 U 盘或scp传到目标机器再用apt-key add file.asc或方法二导入。5.2 密钥 ID 找不到或已过期错误信息中的密钥 ID 可能在密钥服务器上不存在或者已被撤销Revoked。排查步骤验证密钥 ID再次确认错误信息中的密钥 ID 是否抄写正确。长 ID16位更可靠。搜索密钥信息在浏览器中访问https://keyserver.ubuntu.com/pks/lookup?opgetsearch0x[KEY_ID]查看密钥详情。如果返回“Key not found”说明该 ID 无效。查找正确的密钥访问软件源官网最可靠的方法是去添加该软件源的官方网站或 GitHub 页面查看最新的安装说明。维护者可能已经更新了密钥。检查源列表中的密钥导入指令有时在.list文件上方会有注释说明如何获取密钥。或者原始的add-apt-repository命令输出中可能包含密钥指纹。使用完整的指纹如果官网提供了完整的 40 位密钥指纹用它来接收密钥会更准确sudo apt-key adv --keyserver ... --recv-keys FULL_FINGERPRINT。5.3 混合使用传统和现代方法导致的冲突如果你在一个系统上既用了apt-key add全局信任又为同一个源配置了[signed-by]局部信任可能会产生混淆但通常不会导致错误因为 APT 只要找到一种有效的验证方式即可。不过为了清晰和安全建议统一到“现代方法”。清理旧的全局密钥首先确保你已经用方法二为所有第三方源配置好了[signed-by]。列出所有通过apt-key添加的第三方密钥sudo apt-key list记住你不认识的或已不再需要的密钥 ID通常不是以“Ubuntu”或“Debian”开头的。删除特定的密钥sudo apt-key del KEY_ID警告删除前请务必确认该密钥没有其他软件源依赖。最安全的方法是在删除前确保对应软件源的.list文件已经正确配置了[signed-by]。5.4 网络代理Proxy环境下的问题在企业或特殊网络环境下所有 HTTP/HTTPS 流量都需要经过代理。这会影响apt update下载索引文件也可能影响gpg连接密钥服务器。解决方案为apt配置代理在/etc/apt/apt.conf.d/目录下创建一个文件如99proxy内容如下Acquire::http::Proxy http://your-proxy-ip:port; Acquire::https::Proxy http://your-proxy-ip:port;如果代理需要认证格式为http://username:passwordproxy-ip:port。为gpg配置代理编辑~/.gnupg/gpg.conf用户级或/etc/gnupg/gpg.conf系统级添加keyserver-options http-proxyhttp://your-proxy-ip:port keyserver-options https-proxyhttp://your-proxy-ip:port为curl/wget配置代理如果你使用方法二中的curl或wget下载密钥文件也需要为它们设置代理环境变量export http_proxyhttp://your-proxy-ip:port export https_proxyhttp://your-proxy-ip:port sudo -E curl ... # -E 参数保留环境变量5.5 系统时间不正确导致验证失败GPG 签名包含时间戳。如果你的系统时间与真实时间偏差太大通常是落后很多可能会导致签名被判定为“来自未来”而验证失败。错误可能不直接显示时间问题但表现为无法验证签名。解决方法sudo timedatectl set-ntp true # 启用 NTP 时间同步 sudo timedatectl status # 检查时间和时区或者手动设置时间sudo date -s 2024-05-27 10:00:006. 预防措施与最佳实践解决问题固然重要但防患于未然更能提升效率。以下是一些避免遇到NO_PUBKEY错误的建议。6.1 谨慎添加第三方软件源优先使用官方仓库和 Snap/FlatpakUbuntu 官方仓库的软件已经过充分测试和集成。对于较新或特定的软件优先考虑使用 Snap 或 Flatpak 格式的通用包它们通常自带依赖和签名不干扰系统包管理。信任来源只从软件项目的官方文档中添加 PPA 或源。避免使用来路不明的博客或脚本它们可能包含过时或不正确的源地址和密钥信息。使用add-apt-repository对于 Launchpad PPA尽量使用sudo add-apt-repository ppa:user/ppa命令添加它会自动处理密钥导入尽管是传统方式。这比手动编辑.list文件更可靠。6.2 采用“现代方法”管理密钥对于非 PPA 的第三方源养成使用“方法二”的习惯创建/etc/apt/keyrings/目录。将公钥下载到该目录下。在源文件.list中使用deb [signed-by/etc/apt/keyrings/keyfile.gpg] ...的格式。 这样做隔离性好便于管理。6.3 定期维护与清理移除不用的软件源定期检查/etc/apt/sources.list.d/目录删除不再使用的.list文件。同时删除对应的密钥文件如果在/etc/apt/keyrings/下。更新密钥环偶尔运行sudo apt install --reinstall ubuntu-keyring可以更新官方密钥。查看更新错误每次sudo apt update后留意输出的警告W和错误E信息及时处理不要积压问题。6.4 编写可复现的脚本如果你是系统管理员或者需要经常在多个机器上配置相同的环境可以将添加软件源和密钥的过程写成脚本。下面是一个遵循现代最佳实践的脚本示例#!/bin/bash # 添加 Docker 官方源和密钥的示例脚本 REPO_KEYRING/etc/apt/keyrings/docker.asc REPO_LIST_FILE/etc/apt/sources.list.d/docker.list # 1. 安装依赖工具 sudo apt-get update sudo apt-get install -y ca-certificates curl # 2. 创建密钥环目录 sudo mkdir -p /etc/apt/keyrings # 3. 下载 Docker 官方 GPG 密钥 sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o $REPO_KEYRING # 4. 设置正确的权限 (可选但推荐) sudo chmod ar $REPO_KEYRING # 5. 添加 Docker 软件源 (以 Ubuntu Jammy 22.04 为例) echo deb [arch$(dpkg --print-architecture) signed-by$REPO_KEYRING] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee $REPO_LIST_FILE /dev/null # 6. 更新 APT 索引 sudo apt-get update # 7. 现在可以安装 Docker 了 # sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin这个脚本的优点在于清晰、可重复、遵循安全最佳实践并且明确指出了密钥和源的绑定关系。遇到ubuntu apt update报错“由于没有公钥无法验证下列签名”本质上是一个系统安全机制在正常工作。它迫使你确认软件源的可靠性。通过本文梳理的从原理到实践的完整路径你应该能够诊断出问题根源并根据具体情况选择最合适的解决方案——无论是快速使用传统的apt-key命令还是遵循更安全的“下载密钥文件并绑定源”的现代方法。记住核心思路找到缺失的密钥 ID - 获取正确的公钥 - 将其以适当的方式全局或局部添加到系统的信任链中。在操作中优先查阅软件源的官方文档保持系统时间准确并在网络特殊环境下注意代理配置。养成良好的软件源管理习惯这类问题出现的频率就会大大降低。