distributing-tauri-for-macos
Tauri macOS Distribution
This skill covers distributing Tauri v2 applications on macOS, including DMG installers and application bundle configuration.
Overview
macOS distribution for Tauri apps involves two primary formats:
- Application Bundle (.app) - The executable directory containing all app components
- DMG Installer (.dmg) - A disk image that wraps the app bundle for easy drag-and-drop installation
Building for macOS
Build Commands
Generate specific bundle types using the Tauri CLI:
# Build app bundle only
npm run tauri build -- --bundles app
yarn tauri build --bundles app
pnpm tauri build --bundles app
cargo tauri build --bundles app
# Build DMG installer only
npm run tauri build -- --bundles dmg
yarn tauri build --bundles dmg
pnpm tauri build --bundles dmg
cargo tauri build --bundles dmg
# Build both
npm run tauri build -- --bundles app,dmg
Application Bundle Structure
The .app directory follows macOS conventions:
<productName>.app/
Contents/
Info.plist # App metadata and configuration
MacOS/
<app-name> # Main executable
Resources/
icon.icns # App icon
[bundled resources] # Additional resources
_CodeSignature/ # Code signature files
Frameworks/ # Bundled frameworks
PlugIns/ # App plugins
SharedSupport/ # Support files
DMG Installer Configuration
Configure DMG appearance in tauri.conf.json:
Complete DMG Configuration Example
{
"bundle": {
"macOS": {
"dmg": {
"background": "./images/dmg-background.png",
"windowSize": {
"width": 660,
"height": 400
},
"windowPosition": {
"x": 400,
"y": 400
},
"appPosition": {
"x": 180,
"y": 220
},
"applicationFolderPosition": {
"x": 480,
"y": 220
}
}
}
}
}
DMG Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
background |
string | - | Path to background image relative to src-tauri |
windowSize.width |
number | 660 | DMG window width in pixels |
windowSize.height |
number | 400 | DMG window height in pixels |
windowPosition.x |
number | - | Initial window X position on screen |
windowPosition.y |
number | - | Initial window Y position on screen |
appPosition.x |
number | 180 | App icon X position in window |
appPosition.y |
number | 220 | App icon Y position in window |
applicationFolderPosition.x |
number | 480 | Applications folder X position |
applicationFolderPosition.y |
number | 480 | Applications folder Y position |
Note: Icon sizes and positions may not apply correctly when building on CI/CD platforms due to a known issue with headless environments.
Info.plist Customization
Creating a Custom Info.plist
Create src-tauri/Info.plist to extend the default configuration. The Tauri CLI automatically merges this with generated values.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Privacy Usage Descriptions -->
<key>NSCameraUsageDescription</key>
<string>This app requires camera access for video calls</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access for audio recording</string>
<key>NSLocationUsageDescription</key>
<string>This app requires location access for mapping features</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to import images</string>
<!-- Document Types -->
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>My Document</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>mydoc</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
<!-- URL Schemes -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
</dict>
</plist>
Common Info.plist Keys
| Key | Description |
|---|---|
NSCameraUsageDescription |
Camera access explanation |
NSMicrophoneUsageDescription |
Microphone access explanation |
NSLocationUsageDescription |
Location access explanation |
NSPhotoLibraryUsageDescription |
Photo library access explanation |
NSAppleEventsUsageDescription |
AppleScript/automation access |
CFBundleDocumentTypes |
Supported document types |
CFBundleURLTypes |
Custom URL schemes |
LSMinimumSystemVersion |
Minimum macOS version (prefer tauri.conf.json) |
Info.plist Localization
Support multiple languages with localized strings:
Directory structure:
src-tauri/
infoplist/
en.lproj/
InfoPlist.strings
de.lproj/
InfoPlist.strings
fr.lproj/
InfoPlist.strings
es.lproj/
InfoPlist.strings
Example InfoPlist.strings (German):
"NSCameraUsageDescription" = "Diese App benötigt Kamerazugriff für Videoanrufe";
"NSMicrophoneUsageDescription" = "Diese App benötigt Mikrofonzugriff für Audioaufnahmen";
Configure in tauri.conf.json:
{
"bundle": {
"resources": {
"infoplist/**": "./"
}
}
}
Entitlements Configuration
Entitlements grant special capabilities when your app is code-signed.
Creating Entitlements.plist
Create src-tauri/Entitlements.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- App Sandbox (required for App Store) -->
<key>com.apple.security.app-sandbox</key>
<true/>
<!-- Network Access -->
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<!-- File Access -->
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<!-- Hardware Access -->
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
<!-- Hardened Runtime -->
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>
Configure Entitlements in tauri.conf.json
{
"bundle": {
"macOS": {
"entitlements": "./Entitlements.plist"
}
}
}
Common Entitlements Reference
Sandbox Entitlements:
| Entitlement | Description |
|---|---|
com.apple.security.app-sandbox |
Enable app sandbox (required for App Store) |
com.apple.security.network.client |
Outbound network connections |
com.apple.security.network.server |
Incoming network connections |
com.apple.security.files.user-selected.read-write |
Access user-selected files |
com.apple.security.files.downloads.read-write |
Access Downloads folder |
Hardware Entitlements:
| Entitlement | Description |
|---|---|
com.apple.security.device.camera |
Camera access |
com.apple.security.device.microphone |
Microphone access |
com.apple.security.device.usb |
USB device access |
com.apple.security.device.bluetooth |
Bluetooth access |
Hardened Runtime Entitlements:
| Entitlement | Description |
|---|---|
com.apple.security.cs.allow-jit |
Allow JIT compilation |
com.apple.security.cs.allow-unsigned-executable-memory |
Allow unsigned executable memory |
com.apple.security.cs.disable-library-validation |
Load arbitrary plugins |
macOS Bundle Configuration
Complete macOS Configuration Example
{
"bundle": {
"icon": ["icons/icon.icns"],
"macOS": {
"minimumSystemVersion": "10.13",
"entitlements": "./Entitlements.plist",
"frameworks": [
"CoreAudio",
"./libs/libcustom.dylib",
"./frameworks/CustomFramework.framework"
],
"files": {
"embedded.provisionprofile": "./profiles/distribution.provisionprofile",
"SharedSupport/README.md": "./docs/README.md"
},
"dmg": {
"background": "./images/dmg-background.png",
"windowSize": {
"width": 660,
"height": 400
},
"appPosition": {
"x": 180,
"y": 220
},
"applicationFolderPosition": {
"x": 480,
"y": 220
}
}
}
}
}
Minimum System Version
Set the minimum supported macOS version:
{
"bundle": {
"macOS": {
"minimumSystemVersion": "12.0"
}
}
}
Default: macOS 10.13 (High Sierra)
Including Frameworks and Libraries
Bundle system frameworks or custom dylib files:
{
"bundle": {
"macOS": {
"frameworks": [
"CoreAudio",
"AVFoundation",
"./libs/libmsodbcsql.18.dylib",
"./frameworks/Sparkle.framework"
]
}
}
}
- System frameworks: Specify name only (e.g.,
"CoreAudio") - Custom frameworks/dylibs: Provide path relative to
src-tauri
Adding Custom Files to Bundle
Include additional files in the bundle's Contents directory:
{
"bundle": {
"macOS": {
"files": {
"embedded.provisionprofile": "./profile.provisionprofile",
"SharedSupport/docs/guide.pdf": "./assets/guide.pdf",
"Resources/config.json": "./config/default.json"
}
}
}
}
Format: "destination": "source" where paths are relative to tauri.conf.json
Troubleshooting
Common Issues
DMG icons not positioned correctly on CI/CD:
- This is a known issue with headless environments
- Consider building DMGs locally or accepting default positioning
App rejected due to missing usage descriptions:
- Add all required
NS*UsageDescriptionkeys toInfo.plist - Ensure descriptions clearly explain why access is needed
Entitlements not applied:
- Verify the entitlements file path in
tauri.conf.json - Ensure the app is properly code-signed
Framework not found at runtime:
- Check framework path is correct relative to
src-tauri - Verify framework is properly signed
Verification Commands
# Check Info.plist contents
plutil -p path/to/App.app/Contents/Info.plist
# Verify entitlements
codesign -d --entitlements - path/to/App.app
# Check code signature
codesign -vvv --deep --strict path/to/App.app
# View bundle structure
find path/to/App.app -type f | head -50
Quick Reference
File Locations
| File | Location | Purpose |
|---|---|---|
Info.plist |
src-tauri/Info.plist |
App metadata extensions |
Entitlements.plist |
src-tauri/Entitlements.plist |
Capability entitlements |
DMG Background |
Any path in project | DMG window background |
Localized strings |
src-tauri/infoplist/<lang>.lproj/ |
Localized Info.plist values |
Build Output Locations
src-tauri/target/release/bundle/
macos/
<ProductName>.app # Application bundle
dmg/
<ProductName>_<version>_<arch>.dmg # DMG installer