Code Signing
A guide to code signing your Tauri v2 application for Windows, macOS, and Linux, explaining why it is required and how to configure it.
Code signing proves that an application came from you and hasn’t been altered since you built it. When you distribute a Tauri desktop app, the operating system checks for a valid digital signature. Without one, Windows shows a SmartScreen warning and macOS either blocks launch entirely or flags the app as damaged. This guide covers setting up code signing on all three platforms, using only the configuration Tauri already supports. Start with Why Code Signing if you need the rationale before the how.
Why Code Signing?
Every modern desktop OS verifies software identity before trusting it. Windows uses SmartScreen and Authenticode signatures. macOS uses Gatekeeper, which refuses to run unsigned or unnotarized apps unless users dig into security settings. On Linux, most desktop environments don’t enforce signatures, but package managers and centralized app stores do.
A code signature serves two purposes. First, it attaches a verified publisher identity to the binary, so users know who built the app. Second, it creates a cryptographic hash of the executable and signs that hash with a private key. If someone modifies the binary after signing, the hash changes and the OS detects tampering.
During Development:
You can run and test your Tauri app locally without any code signing. These requirements only matter when you distribute the final installer or binary to other people.
A common misconception is that an SSL certificate for a website can sign desktop apps. That doesn’t work. You need a specific code signing certificate issued by a Certificate Authority (CA) that operating systems trust. The process of acquiring one differs by platform, as shown in the following sections.
Windows Code Signing
Windows signing uses Authenticode. Tauri automatically runs signtool.exe with the parameters you provide in tauri.conf.json. You have two main paths for managing the signing key. Step-by-step setup is on Windows Code Signing.
- Local OV certificate – you hold a
.pfxfile on your build machine. This is the simplest route for individuals and small teams. - Azure Key Vault – the signing key lives in Microsoft’s cloud HSM. No private key file exists on your machine. This is often preferred in CI/CD environments.
Choose one method. The configuration fields in tauri.conf.json are different for each.
Signing with a Local OV Certificate
An Organization Validated (OV) code signing certificate from a CA like SSL.com, DigiCert, or Sectigo works for most desktop apps. Extended Validation (EV) certificates historically gave instant SmartScreen reputation, but since 2024 SmartScreen reputation builds from download volume for both OV and EV. EV is still required for kernel‑mode drivers; for a Tauri app, OV is sufficient.
Prerequisites
- A code signing certificate (
.ceror.crtfile) and its private key (.keyfile) - OpenSSL available on your system
- Windows PowerShell (the steps use PowerShell commands)
Wrong Certificate Type:
An SSL/TLS certificate for a website cannot be used for code signing. Make sure your certificate is issued for “Code Signing.” If you use an SSL cert, the signing tool will reject it.
Step-by-Step Setup
Convert the certificate to a .pfx file
The .pfx (PKCS#12) format bundles the certificate and private key into a single password‑protected file. In a terminal, run:
openssl pkcs12 -export -in cert.cer -inkey private-key.key -out certificate.pfx
You’ll be prompted to set an export password. Keep this password safe — you’ll need it later.
Import the .pfx into the Windows certificate store
The signing tool looks for certificates in the current user’s personal store. Use PowerShell to import:
$WINDOWS_PFX_PASSWORD = 'YourExportPassword'
Import-PfxCertificate -FilePath certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $WINDOWS_PFX_PASSWORD -Force -AsPlainText)
Find the certificate thumbprint and digest algorithm
Open certmgr.msc, go to Personal → Certificates, double‑click your certificate, and open the Details tab.
- Thumbprint – a 40‑character hex string like
A1B1A2B2.... Copy it without spaces. - Signature hash algorithm – usually
sha256. This becomes thedigestAlgorithm. - Timestamp URL – your CA provides a time‑stamping server, such as
http://timestamp.comodoca.com. Timestamping ensures the signature remains valid after the certificate expires.
Add the signing configuration to tauri.conf.json
Inside src-tauri/tauri.conf.json, locate the bundle > windows section and fill in the values:
{
"bundle": {
"windows": {
"certificateThumbprint": "A1B1A2B2A3B3A4B4A5B5A6B6A7B7A8B8A9B9A0B0",
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.comodoca.com"
}
}
}
Build and verify the signature
Run npm run tauri build (or your project’s build command). In the console output you should see:
info: signing app
info: running signtool "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\signtool.exe"
info: "Done Adding Additional Store\r\nSuccessfully signed: APPLICATION FILE PATH HERE"
Signature Verified:
If you see “Successfully signed” followed by the path to your .exe, Windows will now trust your application when downloaded via a browser.
Storing Secrets for CI/CD
Build machines in GitHub Actions or other CI environments need the certificate too. Export the .pfx as a base64 string and store it as a secret.
certutil -encode certificate.pfx base64cert.txt
The content of base64cert.txt is your WINDOWS_CERTIFICATE secret. Also store the export password as WINDOWS_CERTIFICATE_PASSWORD. In your workflow, add a step before the Tauri build to import the certificate:
- name: Import Windows certificate
if: matrix.platform == 'windows-latest'
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
New-Item -ItemType directory -Path certificate
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
Remove-Item -path certificate -include tempCert.txt
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
Never Commit Certificate Files:
Any file containing your private key — .pfx, .p12, .key, or the base64 representation — must be excluded from version control. Add them to .gitignore immediately.
macOS Code Signing
Apple’s security model requires two separate steps: code signing and notarization. Code signing embeds your Developer ID certificate into the app bundle. Notarization uploads the signed app to Apple’s servers, where it’s scanned for malware. If it passes, Apple staples a ticket to the app so Gatekeeper trusts it. The macOS Code Signing page has the certificate and notarization steps.
Tauri automatically handles notarization during tauri build when you supply the right credentials. You don’t need to run extra commands.
Apple Developer Account
A paid Apple Developer account ($99/year) is mandatory for notarization. The free tier only works for local development and testing. Enroll at developer.apple.com/programs/enroll.
Creating a Developer ID Certificate
Only the Account Holder role can create Developer ID certificates. If you belong to an organization, the account holder must perform these steps.
Generate a Certificate Signing Request (CSR)
Open Keychain Access on your Mac. From the menu bar, choose Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority. Fill in your email address, leave the CA Email field empty, select Saved to disk, and save the .certSigningRequest file.
Submit the CSR to Apple
Go to the Apple Developer certificates page, click the + button, choose Developer ID Application, and upload your .certSigningRequest file. Download the resulting .cer file.
Install the certificate
Double‑click the downloaded .cer file. It will be added to your login keychain. To verify, run:
security find-identity -v -p codesigning
The output contains a line like "Developer ID Application: Your Name (TEAMID)". That entire quoted string is your signing identity.
Entitlements for the WebView
Tauri’s WebView needs two entitlements to run JavaScript. Create src-tauri/Entitlements.plist with the following content:
<?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>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>
If these entitlements are missing, the WebView will crash silently or the app will fail to launch.
Configuring tauri.conf.json for macOS
Add the signing identity and entitlements path to src-tauri/tauri.conf.json inside the bundle > macOS section:
{
"bundle": {
"macOS": {
"signingIdentity": "Developer ID Application: Your Name (TEAMID)",
"entitlements": "./Entitlements.plist",
"minimumSystemVersion": "11.0",
"dmg": {
"appPosition": { "x": 180, "y": 170 },
"applicationFolderPosition": { "x": 480, "y": 170 }
}
}
}
}
The DMG position values control where the app icon and the Applications folder shortcut appear in the disk image window.
Notarization Credentials
Tauri needs credentials to communicate with Apple’s notary service. You can use your Apple ID with an app‑specific password, or a more secure App Store Connect API key.
Generate an app‑specific password at appleid.apple.com under Sign‑In and Security → App‑Specific Passwords. Note your Team ID from the Apple Developer membership page.
Set these environment variables before running tauri build:
| Variable | Value |
|---|---|
APPLE_ID | Your Apple ID email address |
APPLE_PASSWORD | The app‑specific password (not your main Apple ID password) |
APPLE_TEAM_ID | Your 10‑character Team ID |
App‑Specific Password Security:
The APPLE_PASSWORD value is an app‑specific password, not your Apple ID account password. Never use your account password for this purpose — if it leaks, an attacker could access your entire Apple account.
When you run npm run tauri build, Tauri signs the app, uploads it for notarization, polls until it completes, and staples the ticket. A successful build produces a .dmg that opens on any Mac without a security warning.
Exporting the Certificate for CI
Your local Mac has the certificate in its keychain, but CI runners need it too. Export the certificate and its private key as a password‑protected .p12 file:
- Open Keychain Access, click My Certificates, find your Developer ID certificate, and expand it to reveal the private key beneath it.
- Right‑click the private key, choose Export, and save as
.p12with a strong password. - Convert to base64:
base64 -i certificate.p12 -o certificate-base64.txt
Store the content of certificate-base64.txt as the secret APPLE_CERTIFICATE and the password as APPLE_CERTIFICATE_PASSWORD in your CI environment. In a GitHub Actions workflow, import the certificate before the Tauri build:
- name: Import Apple certificate
if: matrix.platform == 'macos-latest'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12
security create-keychain -p "" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "" build.keychain
security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -A
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
Delete Local Copies After Exporting:
The .p12 and certificate-base64.txt files contain your private key. Once they are stored as GitHub secrets, delete them from your local disk and ensure they never appear in version control.
Linux Considerations
Linux desktop distributions do not have a unified code signing requirement like Windows or macOS. An unsigned AppImage or .deb package will run on most systems without warnings. However, if you plan to distribute through official repositories (Flathub, Snap Store, apt repositories), package signing becomes important. See Linux Considerations.
For AppImage, you can sign the file with GPG and provide a signature file alongside the download. This lets users verify the binary’s integrity manually. Signing looks like:
gpg --detach-sign --armor YourApp.AppImage
This produces YourApp.AppImage.asc. Users verify with:
gpg --verify YourApp.AppImage.asc YourApp.AppImage
For deb packages, a GPG key is used to sign the repository metadata, not each individual package. You would set up a PPA or a custom apt repository with a signed Release file.
For Flatpak, Flathub requires build validation but does not require a separate code signing certificate from the developer. The Flatpak build process itself is sandboxed and verified by the Flathub infrastructure.
The Tauri bundler does not currently include built‑in GPG signing for AppImage or deb. You would add a post‑build script that signs the artifacts after tauri build completes. Most Tauri developers distributing on Linux rely on the security model of the app store or repository they publish to, and provide signature files for direct downloads as a best practice.
No Certificate Purchase Required:
Unlike Windows and macOS, Linux code signing does not require purchasing a certificate from a CA. You generate your own GPG key pair and publish the public key.
Summary
Code signing is the final step that turns a working Tauri app into a distributable product users can install without scary warnings. The exact setup differs by platform, but the pattern is the same: obtain a certificate trusted by the OS, tell Tauri where to find it, and supply credentials so the build pipeline can sign and notarize automatically.
For Windows, an OV certificate in your local store or an Azure Key Vault‑backed setup both integrate cleanly with Tauri’s build system. For macOS, a Developer ID certificate plus notarization credentials unlock a Gatekeeper‑free installation experience. On Linux, signing is optional but easy to add with GPG.
Why Code Signing?
Learn what code signing is and why it is essential for security, user trust, and meeting platform requirements when distributing Tauri desktop applications.
Windows Code Signing
Secure your Tauri v2 application for Windows distribution by code signing with OV certificates or Azure Key Vault to avoid SmartScreen blocks and build user trust
macOS Code Signing
A step‑by‑step guide to code signing and notarizing Tauri v2 applications for macOS, so users can open your app without Gatekeeper warnings.
Linux Considerations
How to code sign Tauri v2 applications on Linux across AppImage, DEB, and RPM package formats, including key management and verification