00 / 00

自动更新

为 01MVP Desktop 配置 Tauri updater、签名产物和更新端点

你将学到

  • 自动更新需要哪三样东西才能跑起来
  • 为什么模板默认没启用 updater
  • tauri signer generate 生成签名密钥
  • 配置 Tauri 让应用知道去哪检查更新
  • 搭建一个返回正确格式的更新端点
  • 在应用内调用检查更新并处理四种状态

自动更新需要什么

桌面自动更新不是前端按一个按钮就行。它需要三样东西配合:

  1. 签名密钥 — 你的构建产物(DMG、MSI、AppImage)需要被签名。客户端拿到更新后会用公钥验证,确保安装包没被篡改。
  2. 更新端点 — 一个可访问的 HTTP 地址,应用启动时会请求它,告诉客户端"有没有新版本、去哪下载"。
  3. 应用内配置 — Tauri 的 updater plugin、端点地址、公钥,以及前端的检查更新逻辑。

这三样缺一个,更新流程就走不通。

为什么模板没默认开

模板保留了 src/runtime/updater.ts 的入口,但没启用 Rust 端的 updater plugin。原因是:自动更新需要真实发布域名、签名密钥对、每个平台的安装包和版本策略。如果模板写个假 endpoint,应用启动时反而容易出错。

当前做法是:未配置时 checkForDesktopUpdate() 返回 unavailable,应用正常启动,不报错。

如果还没有稳定下载域名和 updater 私钥,先保留"检查更新不可用"的状态。不要用临时 URL 做生产更新源。

第一步:生成签名密钥

Tauri 用 Ed25519 密钥对签名更新包。运行官方命令生成:

pnpm exec tauri signer generate --write-keys

命令会输出公钥和私钥。私钥保存在本地安全位置,公钥后面要写进 tauri.conf.json

私钥只放在 CI secret 或本机安全位置。别把 updater 私钥提交到仓库。

第二步:配置 Tauri

src-tauri/tauri.conf.json 中配置 updater:

{
  "bundle": {
    "createUpdaterArtifacts": true
  },
  "plugins": {
    "updater": {
      "endpoints": [
        "https://updates.example.com/{{target}}/{{arch}}/{{current_version}}"
      ],
      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWdu..."
    }
  }
}

endpoints 数组里可以放多个地址做容灾。模板变量 {{target}}{{arch}}{{current_version}} 会被运行时替换。

同时确保这些文件也改了:

文件改什么
src-tauri/Cargo.toml添加 tauri-plugin-updater 依赖
src-tauri/src/lib.rs注册 updater plugin(.plugin(tauri_plugin_updater::init())
src-tauri/capabilities/default.json开放 updater 权限

package.json 里的 @tauri-apps/plugin-updater 已经在模板里保留了,不需要额外安装。

第三步:搭建更新端点

端点可以是静态 JSON,也可以是服务端 API。推荐服务端 API,因为它能按平台、架构和版本返回不同结果。

端点至少要返回这些字段:

{
  "version": "0.2.0",
  "notes": "修复了窗口拖拽问题,新增系统托盘菜单",
  "pub_date": "2026-06-07T12:00:00Z",
  "platforms": {
    "darwin-aarch64": {
      "signature": "dW50cnVzdGVkIGNvbW1lbnQ...",
      "url": "https://releases.example.com/app_0.2.0_aarch64.app.tar.gz"
    },
    "darwin-x86_64": {
      "signature": "dW50cnVzdGVkIGNvbW1lbnQ...",
      "url": "https://releases.example.com/app_0.2.0_x64.app.tar.gz"
    },
    "windows-x86_64": {
      "signature": "dW50cnVzdGVkIGNvbW1lbnQ...",
      "url": "https://releases.example.com/app_0.2.0_x64-setup.nsis.zip"
    }
  }
}

安装包放 R2、S3、GitHub Releases 或对象存储都行。闭源产品用 Cloudflare Worker + R2 更容易控制访问、缓存和下载统计。

如果当前版本已是最新,端点返回 HTTP 204 或空 body 即可,Tauri 会识别为"无更新"。

第四步:启用 Rust plugin

src-tauri/src/lib.rs 的 Tauri builder 中注册 plugin:

.plugin(tauri_plugin_updater::Builder::new().build())

然后在 src-tauri/capabilities/default.json 里开放权限。如果只需要检查更新:

["updater:allow-check"]

等下载和安装流程准备好后,再开放完整权限:

["updater:allow-check", "updater:allow-download", "updater:allow-install"]

第五步:应用内检查更新

模板入口在 products/01mvp/apps/desktop/src/runtime/updater.ts。启用 Rust updater plugin 后,checkForDesktopUpdate() 会返回以下状态之一:

status含义
available有新版本,包含版本号和 release notes
none当前版本已是最新
unavailable当前构建没有配置 updater
failed网络错误或端点异常

先只做"检查更新"按钮就够了。自动下载、静默安装这些等发布流程稳定后再加。

验证

启用自动更新后,按这个顺序跑一遍:

  1. 打开应用,点"检查更新" — 当前是最新版本时应显示 up to date
  2. 部署一个新版本 — 确认端点返回正确版本号和 notes
  3. 再次检查更新 — 应该看到新版本
  4. 确认下载 URL 可访问,签名校验通过
  5. 从旧版本完成一次完整更新流程
  6. macOS、Windows、Linux 分别验证
  7. 关闭端点或断网测试 — 确认 UI 不崩溃
  8. 没配置 updater 的开发构建仍能正常启动

每次发布后,用旧版本真实安装包跑一遍"检查更新 -> 下载 -> 安装"。CI 可以负责构建、签名、上传和发布 manifest,但下面这些需要你提前准备好:

  • updater 私钥放进 CI secret,不能进仓库
  • 下载域名和对象存储已经可访问
  • preview / production 的 endpoint 分开

常见问题

为什么不能直接用私有 GitHub Release

用户机器上的桌面应用不该内置 GitHub token。私有 Release 直接当 updater 源会有认证和泄漏风险。更稳的做法是后端服务决定是否允许下载,再把短期可访问的安装包地址返回给客户端。

dev 构建需要自动更新吗

通常不需要。dev 构建主要用于调试,自动更新应该在 preview 或 production 渠道里测试。

updater 权限要一次性全开吗

不需要。先只开放 updater:allow-check 做检查。等下载和安装流程准备好后,再开放完整权限。

下一步

想和其他创造者交流?

这篇文档有问题?