Skip to content

Ship It: Building and Distribution

Congratulations! You have set up your environment, built a beautiful frontend, connected it to a robust Rust backend, and polished your app with native features. Now, it is time to take your creation out of the development laboratory and ship it to the world. In this chapter, we will transform your source code into optimized, installable binaries.

During development, we used tauri dev. This command focuses on hot-reloading and quick feedback loops. However, the binaries it produces are unoptimized and contain debug symbols, making them large and slow. To create a production-ready application, we use the build command.

Before you run it, you must ensure your application has a unique identifier in tauri.conf.json. If you are still using com.tauri.dev, the build will fail. Change it to something unique, like com.yourname.appname.

src-tauri/tauri.conf.json
{
"identifier": "com.mycompany.awesomeapp",
...
}

Once configured, run the following command in your terminal:

Terminal window
# If using npm
npm run tauri build
# If using cargo directly
cargo tauri build

This command performs a sequence of critical tasks:

  • It runs your frontend build script (e.g., npm run build) to generate the HTML/CSS/JS assets.
  • It compiles the Rust code with the --release flag, enabling aggressive optimizations.
  • It bundles the frontend assets directly into the Rust binary.
  • It generates platform-specific installers (MSI, DMG, DEB, etc.).

Operating systems are protective gatekeepers. If you try to run an application that hasn’t been “vouched for,” the OS will warn the user or block the app entirely. This is where code signing comes in. It is like a digital wax seal that proves the app comes from you and hasn’t been tampered with.

  • macOS: This is the strictest platform. To distribute an app without users seeing a “Damaged and can’t be opened” error, you must sign the app and Notarize it with Apple. This requires an Apple Developer Program membership. Tauri needs your certificate and specific environment variables (like APPLE_CERTIFICATE and APPLE_PASSWORD) to automate this during the build process.
  • Windows: While you can distribute unsigned apps, users will likely see the scary “Windows protected your PC” SmartScreen warning. To avoid this, you need an EV (Extended Validation) or OV code signing certificate. You configure the certificate path and password in your tauri.conf.json or environment variables.
  • Linux: Generally relies on distribution maintainers or formats like AppImage, which don’t strictly enforce code signing in the same way, though signing GPG keys for repositories is common practice.

Tauri is smart enough to generate the appropriate installer for the machine you are building on. You can configure which formats to output in the bundle section of your configuration.

src-tauri/tauri.conf.json
{
"bundle": {
"active": true,
"targets": "all", // or specific targets like ["msi", "nsis"]
...
}
}

Here is what you generally produce for each platform:

PlatformFormatDescription
Windows.msi / .exeThe .msi is a standard Windows Installer. Tauri also supports NSIS (.exe), which is often preferred for a lighter, more custom installation experience.
macOS.dmg / .appThe .app is the executable bundle, while the .dmg (Disk Image) is the standard container used for distribution.
Linux.deb / .AppImage.deb is for Debian/Ubuntu based systems. .AppImage is a portable format that runs on most Linux distributions without installation.
Android.apk / .aabAPK is for direct installation; AAB (Android App Bundle) is required for uploading to the Google Play Store.

Building manually on your local machine is fine for testing, but for a real release, you want consistency. Furthermore, you usually cannot build a macOS app on Windows or vice versa due to the platform-specific WebView bindings. The solution is Continuous Integration (CI).

Tauri provides an official GitHub Action that automates the build and release process. By setting up a workflow file, GitHub will spin up virtual machines (Windows, macOS, and Ubuntu), build your app on all of them simultaneously, and upload the installers to a GitHub Release.

Here is a simplified example of a .github/workflows/release.yml file:

name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
strategy:
fail-fast: false
matrix:
platform: [macos-latest, ubuntu-22.04, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: setup node
uses: actions/setup-node@v4
with:
node-version: 20
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
# Install dependencies (Linux only) needs specific steps here...
- name: Build the app
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tagName: ${{ github.ref_name }}
releaseName: 'App v__VERSION__'
releaseBody: 'See the assets to download this version and install.'
releaseDraft: true
prerelease: false

With this setup, simply pushing a tag like v1.0.0 to your repository will trigger the cloud builders. Minutes later, your GitHub Releases page will be populated with professional installers for every major operating system, ready for your users to download.