DEV Community

Cover image for Code Signing a Tauri App for macOS — The Complete Flow
hiyoyo
hiyoyo

Posted on

Code Signing a Tauri App for macOS — The Complete Flow

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)