适用场景:你在 Tauri 项目里启用了自动更新(updater),然后在
npm run tauri build时遇到类似报错:
A public key has been found, but no private key. Make sure to set TAURI_SIGNING_PRIVATE_KEY environment variable.
本文会把事情讲清楚:
- 为什么需要密钥(公钥/私钥)
- 密钥怎么生成
pubkey配在哪- 为什么会出现“有公钥没私钥”的构建报错
- 如何用 PowerShell 正确构建
- 一些最佳实践(密钥是否每次都要生成?怎么保存?怎么脚本化)
1. Tauri 自动更新的签名密钥是做什么的?
Tauri 的自动更新流程里,核心安全问题只有一个:
客户端下载到的更新包必须可信,不能被中间人篡改。
因此 Tauri 采用“签名验证”模型:
- 发布者(你)用私钥(private key)对更新产物进行签名(生成
.sig等签名文件) - 客户端(用户安装的 App)内置公钥(public key / pubkey)
- 客户端下载更新后,用内置公钥验证签名:
- 验证通过:允许安装更新
- 验证失败:拒绝更新(防止被替换成木马包)
一句话总结:
- 私钥:用来签名更新包(必须保密)
- 公钥:打包进 App,用来验证更新包(可以公开)
2. 哪些配置会触发“构建时必须要私钥”?
当你同时满足以下条件时:
- src-tauri/tauri.conf.json 里配置了 updater 的
pubkey - 并且
bundle.createUpdaterArtifacts = true
Tauri 在 tauri build 阶段会尝试生成“自动更新需要的产物”,同时会去做签名工作。
如果它发现:
- 配了
pubkey(说明你要验证签名) - 但构建时没有拿到
private key
就会直接报错:
A public key has been found, but no private key. Make sure to set
TAURI_SIGNING_PRIVATE_KEYenvironment variable.
这其实是一个“防呆保护”:你都声明要验证签名了,那构建产物就必须有签名。
3. 密钥怎么生成?(一次生成,长期使用)
在项目根目录执行(PowerShell):
mkdir .tauri -Force | Out-Null
# 生成私钥文件:.tauri/update.key
# 过程会提示你输入密码(请记住)
npx tauri signer generate -w .tauri\update.key
# 输出对应公钥(复制结果,填到 tauri.conf.json 的 pubkey)
npx tauri signer public-key -f .tauri\update.key
重要结论:
- 密钥只需要生成一次
- 不需要每次打包都生成新的
- 不建议频繁换密钥(换了密钥,旧版本内置的公钥就无法验证新签名,自动更新链可能断掉)
4. pubkey 配在哪?
常见结构如下(仅示意):
{
"bundle": {
"createUpdaterArtifacts": true
},
"plugins": {
"updater": {
"pubkey": "你刚生成的公钥字符串",
"endpoints": [
"https://xxx/latest.json"
]
}
}
}
5. 我遇到的情况:为什么会报“有公钥没私钥”?
我当时的配置已经有:
plugins.updater.pubkey(公钥)bundle.createUpdaterArtifacts: true
因此 Tauri 构建时必须进行签名。
但我的构建环境里没有提供私钥内容(也就是没设置环境变量),所以构建直接失败。
6. 解决方案:构建前设置签名环境变量(PowerShell)
关键点:
TAURI_SIGNING_PRIVATE_KEY不是填路径,而是私钥文件内容- 建议用
-Raw,确保读取为完整字符串(避免换行导致读取成数组)
$env:TAURI_SIGNING_PRIVATE_KEY = Get-Content .tauri\update.key -Raw
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "xxxxx"
npm run tauri build
这样构建就能成功,并且你会在构建产物中看到类似:
xxx-setup.exexxx-setup.exe.sig
.sig 就是用于自动更新校验的签名文件。
7. 最佳实践:如何管理密钥(别翻车)
7.1 私钥绝对不要提交到 git
.gitignore 建议至少包含:
.tauri/update.key
.tauri/*.key
公钥可以公开,但一般也无需提交 .pub 文件,真正用到的是 tauri.conf.json 里的 pubkey 字符串。
7.2 密钥不要每次生成新的
- 同一条更新链必须使用同一套密钥
- 换钥意味着客户端内置的公钥也要更新
而“更新公钥”本身又依赖自动更新链能跑通 —— 容易形成死锁
7.3 别把密码硬编码进仓库
你可以在本机 PowerShell 会话里临时设置(窗口关了就消失),更安全。
8. 进阶:把构建命令脚本化(Windows 推荐 ps1,不要用 sh)
有些同学会写 build.sh 然后 sh build.sh,但在 Windows 上通常没有 sh 环境,容易报:
sh : 无法将“sh”项识别为 cmdlet...
更推荐用 build.ps1(并把它加入 .gitignore)。
示例 build.ps1:
$env:TAURI_SIGNING_PRIVATE_KEY = Get-Content .tauri\update.key -Raw
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "xxxxx"
npm run tauri build
执行:
.\build.ps1
结语
启用 Tauri 自动更新后,“签名密钥”不是可选项,而是安全链路的核心组成部分:
- 公钥写进 App:用于校验更新
- 私钥留在发布端:用于签名更新包
- 构建时没给私钥:就会报“有公钥没私钥”的错误
按本文步骤生成一次密钥,并在每次构建前提供私钥环境变量,就能稳定产出带签名的更新构建产物。