The Updater: Keeping Apps Fresh
The Updater: Keeping Apps Fresh
Section titled “The Updater: Keeping Apps Fresh”Modern users expect software to improve over time without manually downloading installers. Tauri includes a built-in, secure over-the-air (OTA) update system that handles checking for updates, verifying signatures, and installing them.
Configuring the Updater
Section titled “Configuring the Updater”First, you need to add the updater plugin to your project (cargo add tauri-plugin-updater) and initialize it in your Rust code. Then, configure tauri.conf.json to tell the app where to look for updates.
{ "plugins": { "updater": { "endpoints": [ "https://releases.myapp.com/latest.json" ], "pubkey": "YOUR_PUBLIC_KEY_HERE" } }}Signing Updates
Section titled “Signing Updates”Tauri enforces security by requiring all updates to be digitally signed. This prevents a “Man-in-the-Middle” attack where a server is spoofed to serve malware.
You can generate a keypair using the Tauri CLI:
tauri signer generate -w ~/.tauri/myapp.keyThis outputs a public key (safe to share, goes in config) and a private key (keep secret!). During your build process (e.g., GitHub Actions), you must provide the private key via environment variables: TAURI_SIGNING_PRIVATE_KEY and TAURI_SIGNING_PRIVATE_KEY_PASSWORD.
Hosting Update Artifacts
Section titled “Hosting Update Artifacts”The endpoint defined in your config looks for a JSON file containing version information, release notes, and download links for different platforms (Windows, macOS, Linux). When you run tauri build, the CLI generates not just the installers, but also .sig (signature) files and a JSON manifest.
You can host these files anywhere: Amazon S3, GitHub Pages, or a custom VPS. The URL structure in the JSON must point to the actual location of your binaries.
Client-Side Implementation
Section titled “Client-Side Implementation”Finally, you need to tell the app when to check for updates. This is usually done in the frontend when the app launches.
import { check } from '@tauri-apps/plugin-updater';import { relaunch } from '@tauri-apps/plugin-process';
async function checkForAppUpdates() { const update = await check(); if (update) { console.log(`found update ${update.version} from ${update.date} with notes ${update.body}`); let downloaded = 0; let contentLength = 0;
// Download and install the update await update.downloadAndInstall((event) => { switch (event.event) { case 'Started': contentLength = event.data.contentLength; console.log(`started downloading ${contentLength} bytes`); break; case 'Progress': downloaded += event.data.chunkLength; console.log(`downloaded ${downloaded} from ${contentLength}`); break; case 'Finished': console.log('download finished'); break; } });
// Restart the app to apply changes await relaunch(); }}