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
Tauri v2 can produce three standard Linux package formats — AppImage, Debian (.deb), and RPM (.rpm) — plus a plain compressed tarball. Each format fills a different role: AppImage provides a single-file, distro-agnostic executable, while .deb and .rpm integrate directly with the system package manager on Debian-based and Red Hat-based distributions respectively. The bundler handles all three from the same tauri build command, provided the right system tools are available.
The build process wraps your compiled Rust binary, your frontend assets, and any declared resources into a self-contained bundle. For .deb and .rpm, it also generates the metadata that lets the package manager track versions and dependencies. The AppImage bundles shared libraries so no installation is required, but it does not bundle glibc — a detail that has real implications for distribution, which we will cover.
Prerequisites for Building Linux Packages
Before packaging, you need the libraries that Tauri's webview depends on. The bundler also requires specific packaging tools depending on which formats you want to create. The following walkthrough assumes you have already installed Rust and Node.js as described in the Environment Setup chapter.
Step 1: Install the system dependencies
Tauri v2 on Linux requires libwebkit2gtk-4.1 (the WebKit2GTK library with libsoup3) and several other development packages. The exact package names differ by distribution:
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
file \
libxdo-dev \
libssl-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Missing webkit2gtk-4.1 stops the build:
Without webkit2gtk-4.1, the Rust compilation will fail with errors about missing gdk, gtk, or soup headers. This is the single most common build failure on Linux. Double-check that you installed the -dev or -devel variant, not just the runtime library.
Step 2: Install packaging toolchains for your target format
- AppImage — the bundler downloads and runs
appimagetoolautomatically during the build. No extra packages are needed. - DEB — requires
dpkg-deb, which is available by default on Debian and Ubuntu. For other distributions, install thedpkgpackage. - RPM — requires
rpmbuild, present on Fedora and RHEL by default. On Debian/Ubuntu you can installrpmto enable cross-building.
Step 3: Configure the Tauri bundle targets
Open src-tauri/tauri.conf.json and make sure the bundle section lists the Linux formats you want. The relevant top-level keys under bundle are targets, deb, rpm, and appimage.
{
"bundle": {
"active": true,
"targets": ["deb", "appimage", "rpm"],
"deb": {
"depends": []
},
"rpm": {
"depends": []
},
"appimage": {
"bundleMediaFramework": true
}
}
}
targets— an array that may include"deb","appimage","rpm", or"all"(which activates all three).deb.depends— optional extra system packages to declare as dependencies (e.g.,"libxdo3").rpm.depends— the same for RPM packages.appimage.bundleMediaFramework— whentrue(the default), bundles the GStreamer media libraries so audio/video works without the user installing them separately.
Dependency declarations affect whether the app installs cleanly:
If your application uses additional system libraries at runtime — say libpulse for sound or libnotify for notifications — add them to depends. A missing dependency in the package metadata will let the installation succeed but cause runtime crashes.
Step 4: Build the packages
From your project root, run the build command with your preferred package manager:
npm run tauri build
Tauri will first compile your Rust backend in release mode, then bundle the frontend, and finally generate the installer files for every format listed in targets.
Step 5: Locate the output
All generated packages land in src-tauri/target/release/bundle/. You will see a folder for each format:
src-tauri/target/release/bundle/
├── appimage/
├── deb/
└── rpm/
Inside each folder, the installer file and any accompanying metadata files are ready for distribution.
Build verification:
If the terminal output ends with a message like Finished release [optimized] target(s) and no errors, the packaging succeeded. You can immediately run the AppImage or install the .deb/.rpm on a matching test machine.
AppImage
An AppImage is a single, self-contained file that runs on most Linux distributions without installation. Tauri creates it by compiling your application, copying its shared library dependencies into a temporary directory, and packaging everything with appimagetool. The user downloads the file, marks it executable, and runs it.
The format’s core trade-off is that it bundles everything except glibc. The AppImage links against whichever glibc version was present on the build machine, and it will not run on a system with an older glibc. This is the root of most AppImage compatibility complaints.
How the bundler builds the AppImage
During the build, Tauri automatically fetches a precompiled appimagetool binary (if not already cached), then:
- Copies the release binary and all assets into a staging folder that mirrors the final filesystem layout.
- Runs
linuxdeploy(bundled withappimagetool) to discover and copy the shared libraries your binary links against — things likelibgtk-4,libwebkit2gtk-4.1,libssl, and GStreamer plugins whenbundleMediaFrameworkistrue. - Creates the
.AppImagefile from that staging folder.
Configuration reference
The appimage section in tauri.conf.json accepts one key:
bundleMediaFramework(boolean, defaulttrue) — whether to include GStreamer and its plugins. Most apps that play audio or video should leave this on. If your app is purely visual and you want to trim size, set it tofalse.
{
"bundle": {
"appimage": {
"bundleMediaFramework": false
}
}
}
glibc compatibility and workarounds
The AppImage will run on any distribution with a glibc version equal to or newer than the one on the build machine. Building on Ubuntu 24.04 (glibc 2.39) produces an AppImage that requires glibc ≥ 2.39, which excludes older enterprise distributions.
AppImage does not run on older LTS releases out of the box:
If you build on a modern system and try to run the AppImage on Ubuntu 20.04 or CentOS 7, you will see GLIBC_2.XX not found. The only reliable fix is to build on the oldest glibc you intend to support, typically using a container or a VM.
A common strategy is to use a Docker image of the oldest targeted LTS (e.g., Ubuntu 20.04) as a build environment. In that container, install Rust, Node.js, and the Tauri prerequisites, then run npm run tauri build. The resulting AppImage will run on that LTS and any newer release.
For apps that truly need to support a wide range of glibc versions, Flatpak is often a more robust alternative, discussed in Distribution Considerations below.
Debian Package (DEB)
Debian packages (.deb) integrate with apt and dpkg. Users install the app with sudo dpkg -i your-app.deb or sudo apt install ./your-app.deb, and the package manager keeps track of the installation, making upgrades and removal straightforward.
Tauri generates a valid .deb by compiling the binary, placing it under /usr/bin, arranging desktop entry files under /usr/share/applications, and creating the control.tar.gz archive that carries the package metadata (name, version, architecture, dependencies).
Configuration options
The deb section in tauri.conf.json allows you to set:
{
"bundle": {
"deb": {
"depends": [
"libwebkit2gtk-4.1-0",
"libgtk-3-0",
"libayatana-appindicator3-1"
],
"desktopTemplate": "./custom.desktop",
"files": {}
}
}
}
depends— a list of package names thataptwill install automatically before your application. Tauri fills in sensible defaults (libwebkit2gtk-4.1-0,libgtk-3-0, etc.). Extend this list if your app needs extra runtime libraries.desktopTemplate— path to a custom.desktopfile template. Useful when you want to modify the default categories or add MIME type associations. If omitted, Tauri generates one from the app metadata.files— a map of additional files to include in the package, keyed by destination path relative to the package root. For instance, to ship a configuration file, use"/etc/yourapp/config.toml": "./config.toml".
Dependency names vary across Debian versions:
The WebKitGTK runtime package is named libwebkit2gtk-4.1-0 on Debian 12 and Ubuntu 22.04+, but may not exist on older releases. Always test on a clean install of your minimum supported version.
Building a .deb without a Debian system
If you are on Fedora, Arch, or macOS, installing dpkg and fakeroot enables cross-building of .deb packages. On Fedora:
sudo dnf install dpkg-dev fakeroot
Tauri will detect dpkg-deb and generate the .deb as usual.
RPM Package (RPM)
RPM packages (.rpm) serve the same role on Fedora, RHEL, CentOS, openSUSE, and other RPM-based distributions. They are managed with dnf or yum. The bundler produces an .rpm that places the binary under /usr/bin and includes the required desktop and icon files.
Configuration options
The rpm section mirrors the deb section:
{
"bundle": {
"rpm": {
"depends": [
"webkit2gtk4.1",
"gtk3",
"libappindicator-gtk3"
],
"desktopTemplate": "./custom.desktop",
"files": {}
}
}
}
Dependency naming uses the RPM conventions of the build system. On Fedora the WebKit package is webkit2gtk4.1, while on openSUSE it might be libwebkit2gtk-4_0-37. The bundler does not translate names across distributions, so you should either build on the exact target distribution or provide a mapping by overriding depends.
Building an .rpm without an RPM-based system
As with .deb, cross-building requires the rpm-build package. On Debian/Ubuntu:
sudo apt install rpm
The bundler uses rpmbuild to construct the package.
Distribution Considerations
Packaging is only part of the story. Making sure your application actually runs on the users' Linux systems requires understanding the dependency story and choosing the right format for your audience.
The webkit2gtk version lock
Tauri v2 depends on webkit2gtk-4.1, which is built against libsoup3 and requires glib ≥ 2.70. This rules out several older but still supported distributions:
| Distribution | webkit2gtk-4.1 available | Notes |
|---|---|---|
| Ubuntu 22.04+ | Yes | |
| Debian 12+ | Yes | |
| Fedora 37+ | Yes | |
| RHEL 9 / CentOS 9 | No | ships glib 2.68, incompatible |
| Ubuntu 20.04 | No |
If your target audience includes RHEL 9 or Ubuntu 20.04, none of the native package formats will produce a working application — the required WebKit runtime simply cannot be installed from the official repositories.
Flatpak — when you need to cover older systems
Flatpak bundles the entire runtime, including glibc and WebKit, into a sandbox. A Tauri app distributed as a Flatpak can run on any Linux distribution that supports Flatpak, regardless of the host system's library versions. The GNOME runtime provides the exact same WebKitGTK version across all distros.
Building a Flatpak involves writing a manifest file that declares the build steps and dependencies. While Flatpak is not natively integrated into the Tauri CLI bundler, it is the recommended path for broad Linux compatibility and is used by many Tauri applications on Flathub. The manifest approach lets you compile the entire application from source in a container, ensuring reproducible offline builds and solving the glibc problem entirely.
Snap
Similar to Flatpak, Snap packages bundle their dependencies and run in a confined environment. The snapcraft tool creates snaps. If your users are on Ubuntu, Snap offers a native installation experience. The build process requires a snapcraft.yaml that describes the build steps and the required plugs (interfaces for desktop notifications, audio, etc.).
Arch Linux (AUR)
For Arch users, packaging often means a PKGBUILD in the AUR that downloads the binary (or source) and installs it. You can extract the binary and assets from the release tarball or directly use the .tar.gz bundle that Tauri can produce by adding "tar.gz" to the targets array. The PKGBUILD then lists webkit2gtk-4.1 and other runtime dependencies.
Straight binary tarball
Setting targets to ["tar.gz"] produces a gzipped tarball containing only the compiled binary. This is the simplest form of distribution for technical users who know how to install the runtime dependencies themselves. No package metadata, no desktop integration — just the executable.
A bare binary still needs the WebKit runtime:
Regardless of the packaging format, the end user's system must have libwebkit2gtk-4.1 installed or the application will fail to launch with a missing library error. The package formats declaratively pull it in, but a tarball or a binary downloaded from a release page places that responsibility on the user.
Signing and verification
Linux distributions do not uniformly enforce code signing the way macOS does, but for .deb and .rpm repositories you can sign the package metadata with GPG. The Tauri bundler does not sign packages automatically, but you can add a post-build script that calls dpkg-sig or rpm --addsign. Distributing through Flathub or the Snap Store handles verification through their own infrastructure.
Choosing the right format for your users
A practical decision framework:
- If your user base is a mix of modern and older Linux distributions, Flatpak (via Flathub) gives the widest reach with the least platform-specific work.
- If you only support Ubuntu 22.04+ and Debian 12+, the .deb package is the simplest and most familiar.
- If you want a single downloadable file that works on any reasonably current desktop Linux, AppImage is convenient, as long as you build it on the oldest glibc you intend to support.
- For Fedora and RHEL users, the .rpm package integrates natively with their package manager.
- The tarball works well for automated CI deployments or for users who know their system dependencies are already met.
Building on a CI system lets you produce all formats from a single commit: a Docker step with Ubuntu 20.04 for an AppImage that maximizes glibc compatibility, a Debian 12 container for the .deb, and a Fedora 39 container for the .rpm. That matrix covers the ecosystem without forcing you to maintain multiple development machines.
Test on a clean system:
The fastest way to verify a Linux package is to spin up a virtual machine or container with a fresh install of the target distribution, install the package, and launch the app. Relying on a development machine where dependencies are already present hides missing dependency declarations.