自动更新
本教程共 48 篇 · 第 46 篇 · 更新于 2026-08-09 · 约 12 分钟阅读
本节目标:读完你能为 Tauri 应用接入完整的自动更新流程——生成密钥、配置更新源、构建带签名的更新包、在前端或 Rust 端检查并安装更新。
你的应用发布了 v1.0,过了两周修了 bug 想发 v1.1。让所有用户手动下载新版本太痛苦了。Tauri 官方提供了 tauri-plugin-updater 插件,让应用能自动检查更新、下载安装包、验证签名、一键升级。
整体流程
自动更新分四步:
- 构建时:生成更新包(安装文件)和签名文件(.sig)
- 发布时:把更新包和版本信息放到服务器或静态 JSON 文件里
- 运行时:应用向配置的 endpoint 发请求,检查有没有新版本
- 更新时:下载更新包,用公钥验证签名,安装后重启
NoteTauri 的更新器强制验证签名。你不能跳过签名步骤,这是安全设计——防止攻击者注入恶意更新包。
生成签名密钥
更新签名和上一章的代码签名是两套独立的体系。更新签名用的是 Tauri 自己的签名机制,需要一对公私钥。
用 Tauri CLI 生成:
tauri signer generate -w ~/.tauri/myapp.key
这会生成两个文件:
- 私钥(
myapp.key):用于签名更新包,绝对不能泄露 - 公钥(
myapp.key.pub):放在tauri.conf.json里,应用用来验证更新包
Warning私钥丢了就完了——你将无法为已安装应用发布新版本更新。把私钥备份到安全的地方(如密码管理器、加密 USB)。公钥可以随便分享。
安装 updater 插件
Rust 端
cd src-tauri
cargo add tauri-plugin-updater --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
注册插件:
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app| {
#[cfg(desktop)]
app.handle().plugin(tauri_plugin_updater::Builder::new().build());
Ok(())
})
.run(tauri::generate_context!())
.expect("运行 Tauri 应用时出错");
}
前端
npm install @tauri-apps/plugin-updater
权限
在 src-tauri/capabilities/default.json 里加权限:
{
"permissions": [
"core:default",
"updater:default"
]
}
配置 tauri.conf.json
在 plugins.updater 里配置公钥和更新源:
{
"bundle": {
"createUpdaterArtifacts": true
},
"plugins": {
"updater": {
"pubkey": "这里粘贴公钥文件的内容(不是路径)",
"endpoints": [
"https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}"
]
}
}
}
关键配置项:
| 字段 | 说明 |
|---|---|
createUpdaterArtifacts | 设为 true 让构建器生成更新产物和签名 |
pubkey | 公钥内容(字符串,不是文件路径) |
endpoints | 更新源 URL 数组,依次尝试 |
dangerousInsecureTransportProtocol | 设为 true 允许非 HTTPS(仅调试用) |
URL 里可以用三个动态变量:
{{current_version}}:当前应用版本{{target}}:操作系统(windows、darwin、linux){{arch}}:架构(x86_64、aarch64、i686、armv7)
Tip如果从 Tauri v1 迁移过来,把
createUpdaterArtifacts设为"v1Compatible"而不是true。等所有用户都升级到 v2 后再改成true。这个配置将在 v3 移除。
构建更新产物
设好 createUpdaterArtifacts: true 后,tauri build 会在生成安装包的同时产生 .sig 签名文件。
构建前需要设置环境变量:
# Linux / macOS
export TAURI_SIGNING_PRIVATE_KEY="私钥文件路径或内容"
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="私钥密码(如果有)"
# Windows (PowerShell)
$env:TAURI_SIGNING_PRIVATE_KEY="私钥文件路径或内容"
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""
Warning
.env文件不生效!必须用系统环境变量。CI/CD 里用 secrets 注入。
构建后各平台生成的文件:
Linux(target/release/bundle/appimage/):
myapp.AppImage— 应用包(同时是安装包和更新包)myapp.AppImage.sig— 签名文件
macOS(target/release/bundle/macos/):
myapp.app— 应用包myapp.app.tar.gz— 更新用的压缩包myapp.app.tar.gz.sig— 签名文件
Windows(target/release/bundle/nsis/ 和 msi/):
myapp-setup.exe— 安装包(同时是更新包)myapp-setup.exe.sig— 签名文件myapp.msi— MSI 安装包myapp.msi.sig— 签名文件
更新源:静态 JSON 方案
最简单的方案是放一个静态 JSON 文件在 CDN 上(如 GitHub Releases、S3)。应用请求这个 JSON,判断有没有新版本。
JSON 格式:
{
"version": "1.1.0",
"notes": "修复了若干 bug",
"pub_date": "2026-08-09T12:00:00Z",
"platforms": {
"windows-x86_64": {
"signature": "签名文件 .sig 的完整内容",
"url": "https://releases.myapp.com/v1.1.0/myapp-setup.exe"
},
"darwin-x86_64": {
"signature": "签名文件 .sig 的完整内容",
"url": "https://releases.myapp.com/v1.1.0/myapp.app.tar.gz"
},
"linux-x86_64": {
"signature": "签名文件 .sig 的完整内容",
"url": "https://releases.myapp.com/v1.1.0/myapp.AppImage"
}
}
}
关键点:
version必须是合法 SemVer(1.0.0或v1.0.0都行)signature是.sig文件的内容,不是路径也不是 URLplatforms的 key 是OS-ARCH格式- 应用会对比 JSON 里的 version 和当前版本,新版本才会触发更新
TipTauri Action GitHub Action 能自动构建、签名并生成这个 JSON 文件,发布到 GitHub Releases。这是最省心的方案。
更新源:动态服务器方案
如果你需要灰度发布、多通道(stable/beta)、按地区分发等高级功能,可以用动态服务器。
endpoint URL 里的变量会帮你区分请求来源:
https://api.myapp.com/updates/{{target}}/{{arch}}/{{current_version}}
服务器收到请求后:
- 没有更新:返回
204 No Content - 有更新:返回
200 OK+ JSON:
{
"version": "1.1.0",
"pub_date": "2026-08-09T12:00:00Z",
"url": "https://cdn.myapp.com/v1.1.0/myapp-setup.exe",
"signature": "签名内容",
"notes": "更新说明"
}
必填字段是 version、url、signature,其他可选。
Note生产环境强制 HTTPS。
dangerousInsecureTransportProtocol仅用于本地调试。
在前端检查更新
前端 JS API 是最常用的检查更新方式:
import { check } from "@tauri-apps/plugin-updater";
import { relaunch } from "@tauri-apps/plugin-process";
const update = await check();
if (update) {
console.log(`发现新版本 ${update.version}`);
console.log(`更新说明:${update.body}`);
let downloaded = 0;
let contentLength = 0;
// 下载并安装
await update.downloadAndInstall((event) => {
switch (event.event) {
case "Started":
contentLength = event.data.contentLength;
console.log(`开始下载,共 ${contentLength} 字节`);
break;
case "Progress":
downloaded += event.data.chunkLength;
console.log(`已下载 ${downloaded} / ${contentLength}`);
break;
case "Finished":
console.log("下载完成");
break;
}
});
console.log("更新已安装");
await relaunch();
} else {
console.log("当前已是最新版本");
}
check() 返回一个 Update 对象(或 null)。你可以调 update.download() 和 update.install() 分两步走,也可以像上面那样用 downloadAndInstall() 一步到位。
还可以传配置参数:
const update = await check({
timeout: 30000, // 超时毫秒数
headers: { // 自定义请求头
Authorization: "Bearer xxx",
},
target: "windows-x86_64", // 自定义 target(覆盖默认的 OS-ARCH)
});
NoteWindows 上执行
install()时应用会自动退出(Windows 安装程序的限制)。你可以用on_before_exit钩子在退出前做收尾工作。macOS 和 Linux 不会自动退出,你可以选择何时重启。
在 Rust 端检查更新
有些场景你想在 Rust 端自动检查(比如应用启动时后台静默检查):
use tauri_plugin_updater::UpdaterExt;
pub fn run() {
tauri::Builder::default()
.setup(|app| {
let handle = app.handle().clone();
tauri::async_runtime::spawn(async move {
update(handle).await.unwrap();
});
Ok(())
})
.run(tauri::generate_context!())
.unwrap();
}
async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
if let Some(update) = app.updater()?.check().await? {
let mut downloaded = 0;
update
.download_and_install(
|chunk_length, content_length| {
downloaded += chunk_length;
println!("已下载 {} / {:?}", downloaded, content_length);
},
|| {
println!("下载完成");
},
)
.await?;
println!("更新已安装");
app.restart();
}
Ok(())
}
Tip想把下载进度通知前端?用 Tauri 的 Channel(频道)机制在 Rust 和 JS 之间传消息。在 Rust 端用
Channel<DownloadEvent>发送进度事件,前端接收后更新进度条 UI。
Windows 安装模式
Windows 上可以配 installMode 控制安装界面的显示:
{
"plugins": {
"updater": {
"windows": {
"installMode": "passive"
}
}
}
}
三种模式:
passive(默认):显示一个小进度条窗口,无需用户交互。推荐使用。basicUi:显示基本安装界面,需要用户点击完成。quiet:完全无界面,不推荐。此模式下安装程序无法自行请求管理员权限,只在用户级安装或应用已有管理员权限时有效。
运行时高级配置
动态切换更新通道
通过 updater_builder 可以在运行时修改 endpoint:
use tauri_plugin_updater::UpdaterExt;
let channel = if beta { "beta" } else { "stable" };
let url = format!("https://{channel}.myapp.com/{{{{target}}}}/{{{{arch}}}}/{{{{current_version}}}}");
let update = app
.updater_builder()
.endpoints(vec![url])?
.build()?
.check()
.await?;
Tip用
format!()插值 URL 时,Tauri 的变量需要双重转义:{{{{target}}}}而不是{{target}}。
允许降级
默认只更新到更高版本。如果需要回滚(比如新版有严重 bug),自定义版本比较逻辑:
let update = app
.updater_builder()
.version_comparator(|current, update| {
// 默认逻辑:update.version > current
// 改成不等就更新,允许降级
update.version != current
})
.build()?
.check()
.await?;
Windows 退出前钩子
Windows 安装更新时应用会被强制退出。用 on_before_exit 在退出前执行收尾:
let update = app
.updater_builder()
.on_before_exit(|| {
println!("应用即将退出!");
// 保存数据、关闭连接等
})
.build()?
.check()
.await?;
小结
tauri-plugin-updater 为 Tauri 应用提供完整的自动更新能力:用 tauri signer generate 生成签名密钥对,在 tauri.conf.json 配置公钥和 endpoints,构建时设 TAURI_SIGNING_PRIVATE_KEY 环境变量生成带签名的更新包。更新源可选静态 JSON 文件(放 CDN/GitHub Releases)或动态服务器(返回 204 表示无更新,返回 200+JSON 表示有更新)。前端用 check() 检查、downloadAndInstall() 下载安装;Rust 端用 UpdaterExt 在后台静默检查。Windows 安装模式可选 passive/basicUi/quiet。运行时还能动态切换 endpoint、允许降级、设退出前钩子。整套机制强制签名验证,确保更新包来源可信。