Packaging Applications
Learn how to package your Tauri v2 application into platform-specific installers for Windows Linux and macOS using the built-in bundler
After you've built your application for production, the next step is to turn it into something your users can actually install and run. Tauri calls this step packaging — it takes the compiled Rust binary, your frontend assets, and any configured resources, then wraps them into native installers and bundles for each target operating system. This follows Building a Tauri Application.
The entire process is driven by a single CLI command, but what happens under the hood changes dramatically depending on whether you're targeting Windows, Linux, or macOS. This guide covers what each platform expects, how to configure the output, and what can go wrong.
How Packaging Fits Into the Build
Running tauri build does two things by default: it compiles your app in release mode, then packages the result into the formats you've defined in tauri.conf.json. You can separate these steps if you need finer control — for example, to build once and then create both a DMG and an App Store package from the same binary.
The command that triggers everything is the same regardless of platform, though the package manager you use may differ:
npm run tauri build
If you want to skip the bundling step — perhaps you need to sign the binary first or run additional checks — you can pass --no-bundle. Later, a separate tauri bundle command will create the installers from the already-built binary.
Packaging Succeeded:
When the build finishes without errors, your packaged output lands in src-tauri/target/release/bundle/. On Windows you'll find .msi or .exe installers, on Linux .deb, .rpm, or .AppImage files, and on macOS a .dmg disk image alongside a .app bundle.
Which formats actually appear in that folder depends entirely on your tauri.conf.json configuration and the platform you're building on. Each operating system expects different packaging conventions, and the sections that follow walk through them in detail.
Windows Packaging
Windows users expect either a traditional installer that handles shortcuts, uninstallation, and system integration, or a simple executable setup wizard. Tauri can produce both, and you configure them independently. Platform details are on the Windows page.
The two installer formats are:
- MSI — built with the WiX Toolset v3, provides deep Windows Installer integration, including repair and silent installation support.
- NSIS — produces a
-setup.exefile using the Nullsoft Scriptable Install System, which is highly customisable and easier to cross-compile from Linux or macOS.
You control which ones are generated through the bundle.windows section of tauri.conf.json. If both wix and nsis are present, both formats are built.
{
"bundle": {
"windows": {
"wix": {},
"nsis": {}
}
}
}
MSI Requires Windows:
The WiX toolchain can only run on Windows, so .msi installers cannot be created from Linux or macOS hosts. If you're building on a non-Windows machine, limit your config to NSIS or use a CI runner with a Windows environment.
WebView2 Handling
Every Tauri app on Windows depends on Microsoft Edge WebView2 for rendering. It comes pre-installed on Windows 11 and newer Windows 10 builds, but you cannot assume every user has it. The installer needs a strategy for what to do when WebView2 is missing.
Tauri offers four modes, set via bundle.windows.wix.webviewInstallMode or the equivalent nsis field:
| Mode | Internet Needed? | Installer Size Bloat | Notes |
|---|---|---|---|
downloadBootstrapper | Yes | 0 MB | Downloads the bootstrapper on demand; default for both formats. Not recommended for MSI on Windows 7. |
embedBootstrapper | Yes | ~1.8 MB | Ships the tiny bootstrapper inside the installer; better Windows 7 support for MSI. |
offlineInstaller | No | ~127 MB | Bundles the full WebView2 redistributable; required for completely offline environments. |
fixedVersion | No | ~180 MB | Embeds a specific, fixed WebView2 runtime version independent of the system one. |
For most public downloads, downloadBootstrapper keeps the installer small and works well. If you distribute to enterprise environments with no internet access, offlineInstaller is the safe choice.
Skipping WebView2 Is Dangerous:
There is a skip mode, but using it means your app will crash silently on any machine without WebView2 already present. Avoid it unless you have a separate, guaranteed provisioning process.
Cross-Compiling From Linux or macOS
NSIS installers can be cross-compiled from non-Windows hosts, though it requires additional tooling. You'll need to install NSIS itself, the LLVM linker (lld), and the cargo-xwin runner that supplies the Windows SDK headers. The build command then looks like this:
tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc
The output will appear under target/x86_64-pc-windows-msvc/release/bundle/nsis/. This path is useful for CI pipelines that run on Linux runners.
Targeting 32-bit or ARM
By default Tauri builds for the architecture of the host machine — typically 64-bit Intel. If you need a 32-bit installer, install the corresponding Rust target (rustup target add i686-pc-windows-msvc) and pass --target i686-pc-windows-msvc. For ARM64 Windows devices, install the "C++ ARM64 build tools" component from Visual Studio and use --target aarch64-pc-windows-msvc.
Linux Packaging
Linux packaging is less standardised than Windows or macOS — different distributions have different package managers, and what works on Ubuntu won't necessarily feel native on Fedora. Tauri addresses this by generating three formats by default when you build on Linux: AppImage, Debian package (.deb), and RPM (.rpm). The Linux page covers each format.
All three formats share a common truth that every Tauri developer targeting Linux should understand early:
A Standalone Binary Is Not Possible:
You cannot distribute a Tauri Linux app as a single executable without any surrounding package. The application requires WebKitGTK, GTK, and several other system libraries at runtime. These libraries load dynamically and cannot be statically linked into the binary in a practical way. Packaging is mandatory — it ensures those dependencies are declared so the system can satisfy them.
Configuring Linux Bundles
Each format can be tweaked inside bundle.linux in tauri.conf.json. The most common customisation is adding runtime dependencies that your app needs beyond the defaults Tauri includes.
{
"bundle": {
"linux": {
"deb": {
"depends": [
"libwebkit2gtk-4.1-0",
"libgtk-3-0",
"libayatana-appindicator3-1"
]
},
"rpm": {
"depends": [
"webkit2gtk4.1",
"gtk3",
"libayatana-appindicator"
]
}
}
}
}
The dependency names differ between Debian-based and RPM-based distributions, so you'll need to specify them separately. If your app uses the shell plugin or spawns child processes, you may also need to list packages like openssl or libssl3.
Tauri's default depends list covers the core WebKit and GTK libraries, but it's your responsibility to add any extra libraries your Rust code links against. When in doubt, test your package on a clean virtual machine that does not have your development libraries installed.
AppImage Specifics
AppImage is a self-contained format that bundles the application and its key dependencies into a single file users can run without installation. Tauri's AppImage generation uses linuxdeploy and a GTK plugin script to capture the necessary shared libraries. The result is portable across almost any modern Linux distribution, provided FUSE is available on the host.
If you need to bundle additional binaries or libraries not automatically detected, you can add them to the bundle.linux.appimage configuration. The most common example is bundling the xdg-open utility so that external links work on minimal systems.
Missing FUSE on Older Systems:
Some older or container-optimized Linux distributions ship without FUSE (Filesystem in Userspace). Since AppImage requires FUSE to mount its internal filesystem, your users may see an error like fuse: failed to exec fusermount. The workaround is either installing libfuse2 or instructing users to run the AppImage with the --appimage-extract-and-run flag, which bypasses the mount step.
Additional Formats — Snap, Flatpak, and AUR
Tauri's built-in bundler does not produce Snap or Flatpak packages directly. For those, you'll typically create a separate build pipeline that takes the Tauri binary and assets and wraps them in the format's packaging specification. Similarly, Arch User Repository (AUR) packages are usually built from a PKGBUILD script that repackages the .deb or binary release.
These are distribution-specific workflows rather than part of the core packaging step, so they're covered in Distribution later in this chapter.
macOS Packaging
macOS packaging centers on two formats: the .app bundle (a structured directory that macOS treats as an application) and the .dmg disk image (a mountable file that users drag to their Applications folder). Tauri always produces the .app bundle when building on macOS; the DMG is optional but strongly recommended for direct distribution outside the App Store. See macOS.
Both formats demand code signing. Unsigned apps are blocked by Gatekeeper on default macOS installations, and distributing a DMG without notarization triggers a security warning that most users will not bypass. The macOS Code Signing page is the setup walkthrough.
Configuring macOS Bundles
The bundle.macOS section of tauri.conf.json controls both the DMG and the metadata embedded in the .app bundle.
{
"bundle": {
"macOS": {
"dmg": {
"background": "assets/dmg-background.png",
"windowSize": {
"width": 660,
"height": 400
}
},
"minimumSystemVersion": "11.0"
}
}
}
The dmg object lets you set a custom background image and window dimensions for the mounted disk image. The minimumSystemVersion field declares the oldest macOS release your app supports; this gets written into the bundle's Info.plist and affects whether older systems will attempt to launch it.
Code Signing and Notarization
This is not a configuration nicety — it's a hard requirement for any app distributed outside the Mac App Store. The signing identity must match a Developer ID certificate from Apple, and every binary and framework inside the bundle must be signed. After signing, the entire package must be notarized by Apple's service, which staples a ticket to the bundle confirming it was scanned for malware.
The code signing process itself is covered in detail in the Code Signing section of this chapter. From a packaging perspective, the key point is that if your signing identity or entitlements are misconfigured, the tauri build command will fail with a codesign error. You will not get a distributable DMG.
App Store vs Direct Distribution:
The packaging steps described here are for direct distribution (DMG downloads from a website). If you plan to distribute through the Mac App Store, you must use a different signing identity (Apple Distribution) and produce an .app bundle suitable for submission, not a DMG. The tauri bundle command can target the App Store format by passing --bundles app with a separate configuration file.
Building on a Single Platform
macOS builds must happen on macOS hardware. Cross-compilation to macOS from Linux or Windows is not supported in any practical sense, partly because code signing and notarization require Apple-specific command-line tools that only run on macOS. Plan your CI accordingly — you'll need a macOS runner for the final packaging step.
Summary
Packaging a Tauri application means translating a single tauri build invocation into a set of platform-native artifacts your users can open, install, and trust. The configuration lives in tauri.conf.json, and the CLI handles the heavy lifting, but each operating system pulls the result in a different direction:
- Windows demands a decision between MSI and NSIS and a deliberate choice about how to deliver the WebView2 runtime.
- Linux requires you to declare system-level dependencies explicitly, and the AppImage format provides the closest thing to a universal Linux binary despite the underlying library requirements.
- macOS ties packaging inseparably to code signing and notarization — without a valid Apple Developer identity, you cannot ship a working app.
The single most important insight across all three platforms is that packaging is never just about bundling files. It's about meeting the expectations the operating system imposes on how software arrives. Ignoring those expectations — skipping WebView2 on Windows, forgetting a dependency on Linux, or omitting code signing on macOS — doesn't produce a harmless warning; it produces an app that cannot start.
Windows
How to package a Tauri v2 application for Windows using MSI and NSIS installers, configure WebView2 installation, handle code signing, and prepare for distribution.
Packaging for Linux
How to package a Tauri v2 application for Linux using AppImage, DEB, and RPM formats, and key distribution considerations for a React plus Vite frontend
Packaging for macOS
Package your Tauri v2 application for macOS as an app bundle and DMG disk image, configure Info.plist, entitlements, custom files, and handle Intel and Apple Silicon builds