How Tauri's Self-Updater Works: Architecture and Complete Setup Guide
Tauri's self-updater is a built-in, signed, incremental update system that queries remote endpoints, verifies cryptographic signatures, and replaces the running application with platform-specific bundles.
The tauri-apps/tauri repository provides a robust self-updater that enables desktop applications to automatically download and install updates with cryptographic verification. This system integrates seamlessly with the Tauri build pipeline to create signed update bundles for Windows, macOS, and Linux. Understanding how the Tauri self-updater works allows you to deploy secure, automated updates to your users without relying on external package managers.
Architecture of the Tauri Self-Updater
The self-updater consists of three coordinated components defined in the source code: the configuration schema, the bundler that creates update artifacts, and the runtime plugin that handles installation.
Configuration Layer (UpdaterConfig)
The updater behavior is controlled by the UpdaterConfig struct defined in crates/tauri-utils/src/config_v1/mod.rs (lines 2442-2549). This configuration requires:
active: Boolean flag to enable the updaterpubkey: Public RSA key for signature verification (required when active)endpoints: Array of HTTPS URLs supporting template variables like{{current_version}},{{target}}, and{{arch}}dialog: Boolean to enable the built-in native dialog (set tofalsefor custom UIs)
The configuration is parsed by the CLI interface in crates/tauri-cli/src/interface/rust.rs (lines 832-839) and injected into the application at compile time.
Bundle Generation (bundle_project)
When you run tauri build --bundles updater, the bundler executes the bundle_project function in crates/tauri-bundler/src/bundle/updater_bundle.rs (lines 28-41). This creates platform-specific archives:
- Windows: ZIP archive containing the MSI or NSIS installer
- macOS: TAR.GZ archive containing the
.appbundle - Linux: TAR.GZ archive containing the AppImage or binary
The bundler dispatches to platform-specific implementations (bundle_update_windows, bundle_update_macos, bundle_update_linux) and automatically signs the artifacts if a private key is present.
Runtime API and Event System
The @tauri-apps/plugin-updater package exposes the JavaScript API that communicates with the core runtime. Key methods include:
checkUpdate(): Queries the configured endpoints for a new versioninstallUpdate(): Downloads, verifies, and installs the updateonUpdaterEvent(): Listens to lifecycle events likedownload-progress
Behind the scenes, the runtime emits events via app.emit_to("updater", ...) as implemented in crates/tauri/src/lib.rs (lines 979-983), allowing both the built-in dialog and custom UIs to react to update states.
Setting Up the Tauri Self-Updater
Follow these steps to enable signed automatic updates in your Tauri application.
Install the Updater Plugin
Add the official updater plugin to your frontend dependencies:
npm install @tauri-apps/plugin-updater
For Tauri v2, this plugin replaces the legacy core updater. Ensure your tauri.conf.json uses the plugins.updater configuration key.
Configure tauri.conf.json
Add the updater configuration to your tauri.conf.json file:
{
"plugins": {
"updater": {
"active": true,
"dialog": false,
"endpoints": [
"https://mycdn.com/{{target}}/{{arch}}/latest.json"
],
"pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqh..."
}
}
}
The pubkey field must contain the public portion of your signing key pair. The CLI validates this configuration during the build process.
Generate Cryptographic Signing Keys
Create a secure key pair for signing update bundles:
tauri signer generate
This command, implemented in crates/tauri-cli/src/signer/generate.rs, creates a private key saved to $HOME/.tauri-updater.key and prints the public key to stdout. Store the private key securely in your CI environment and paste the public key into tauri.conf.json.
Build Signed Update Bundles
Generate the update artifact for your target platform:
tauri build --bundles updater
The bundler creates the platform-specific archive (ZIP for Windows, TAR.GZ for macOS/Linux) and signs it using your private key. The signature is embedded in the bundle metadata and required for the updater to accept the installation.
Deploy the Update Manifest
Host a JSON manifest at your configured endpoint containing:
{
"version": "1.2.3",
"notes": "Bug fixes and performance improvements",
"pub_date": "2026-02-26T12:00:00Z",
"url": "https://mycdn.com/windows/appname-updater.zip",
"signature": "MEUCIQC..."
}
The signature field contains the Base64-encoded cryptographic signature generated during the build process. The updater downloads the bundle from url only if the version is newer than the running application and the signature validates against your configured public key.
Implement the Frontend Integration
Integrate the updater into your UI using the plugin API:
import { checkUpdate, installUpdate, onUpdaterEvent } from '@tauri-apps/plugin-updater';
async function checkForUpdates() {
const update = await checkUpdate();
if (update) {
const shouldInstall = confirm(`Version ${update.version} is available. Install now?`);
if (shouldInstall) {
await installUpdate();
}
}
}
// Display download progress
onUpdaterEvent('download-progress', ({ progress }) => {
console.log(`Downloading: ${progress}%`);
document.getElementById('progress-bar').style.width = `${progress}%`;
});
If you set "dialog": true in the configuration, you can alternatively call update() from the plugin to display the built-in native dialog that handles the entire flow automatically.
Summary
- Tauri's self-updater uses a three-tier architecture: configuration in
UpdaterConfig, bundling viabundle_project, and runtime APIs exposed through@tauri-apps/plugin-updater. - Cryptographic signing is mandatory; generate keys with
tauri signer generateand store the public key intauri.conf.json. - Platform bundles differ by OS: Windows uses ZIP archives, while macOS and Linux use TAR.GZ.
- Template variables in endpoint URLs (
{{target}},{{arch}},{{current_version}}) allow dynamic routing to platform-specific manifests. - Event-driven UI updates are possible via
onUpdaterEvent, supporting custom progress bars and installation workflows.
Frequently Asked Questions
How does Tauri verify update authenticity?
The Tauri self-updater verifies updates using RSA public-key cryptography. When installUpdate() runs, the runtime downloads the bundle and validates its signature against the pubkey defined in tauri.conf.json (as specified in crates/tauri-utils/src/config_v1/mod.rs). If the signature verification fails, the update is rejected and the application continues running the current version.
What bundle formats does the Tauri self-updater support?
The bundler in crates/tauri-bundler/src/bundle/updater_bundle.rs produces ZIP archives for Windows and TAR.GZ archives for macOS and Linux. Windows packages contain MSI or NSIS installers, macOS packages contain .app bundles, and Linux packages contain AppImages or standalone binaries. These formats are hardcoded in the bundle_project dispatch logic to ensure compatibility with the installation mechanisms of each operating system.
Can I use a custom update server instead of a static JSON file?
Yes. The endpoints configuration accepts any HTTPS URL that returns the required JSON manifest format. You can implement dynamic server-side logic to handle the template variables ({{current_version}}, {{target}}, {{arch}}) and return conditional responses based on request headers, query parameters, or user authentication. The runtime simply performs a GET request and parses the JSON response.
Is the built-in dialog required, or can I build a custom UI?
You can build a completely custom UI by setting "dialog": false in the updater configuration. This disables the native dialog and allows you to use checkUpdate(), installUpdate(), and onUpdaterEvent() to create bespoke update flows with custom styling, progress indicators, and user prompts. The built-in dialog is optional convenience, not a requirement.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →