How to Sign and Notarize a Tauri Mac App for Distribution
All tests run on an 8-year-old MacBook Air.
All results from shipping 7 Mac apps as a solo developer. No sponsored opinion.
Every Mac app I've shipped required this. Here's the exact flow I use.
An unsigned Mac app triggers a Gatekeeper warning that looks like malware. Users close it immediately. Code signing is not optional for a shipping product.
What you need
- Apple Developer account ($99/year)
- Developer ID Application certificate (for distribution outside App Store)
- App-specific password for notarization
Tauri's built-in signing
Tauri v2 handles signing automatically if you configure it:
// tauri.conf.json
{
"bundle": {
"macOS": {
"signingIdentity": "Developer ID Application: Your Name (TEAMID)",
"providerShortName": "TEAMID"
}
}
}
Set environment variables for the build:
export APPLE_SIGNING_IDENTITY="Developer ID Application: Your Name (TEAMID)"
export APPLE_ID="your@email.com"
export APPLE_PASSWORD="your-app-specific-password"
export APPLE_TEAM_ID="YOURTEAMID"
npm run tauri build
Tauri signs the app and submits for notarization automatically.
Manual notarization when needed
Build without auto-notarize
npm run tauri build
Submit DMG manually
xcrun notarytool submit \
"target/release/bundle/dmg/YourApp.dmg" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_PASSWORD" \
--wait
Staple the notarization ticket
xcrun stapler staple "target/release/bundle/dmg/YourApp.dmg"
--wait blocks until notarization completes (usually 1-5 minutes).
Verifying the result
Check signing
codesign -dv --verbose=4 YourApp.app
Check notarization
spctl -a -v YourApp.app
Should output: "accepted"
Check DMG
spctl -a -v YourApp.dmg
The entitlements file
Some capabilities require entitlements. For a Tauri app that runs shell commands:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
com.apple.security.cs.allow-unsigned-executable-memory
com.apple.security.cs.disable-library-validation
Tauri configures entitlements via tauri.conf.json. Check the docs for your specific requirements. For my ADB-based apps, these two entitlements were the minimum needed to run shell commands without Gatekeeper blocking the process.
The $99/year question
Worth it if you're selling apps. Without it, users see a Gatekeeper warning. Many won't proceed. The developer account pays for itself with the first few sales.
If this was useful, a ❤️ helps more than you'd think — thanks!
Hiyoko Kit → https://hiyokomtp.lemonsqueezy.com/checkout/buy/2c94dd0f-e28a-4a17-8efc-7bd93087d46d
X → @hiyoyok
Top comments (0)