Menandatangani Aplikasi
Code Signing Your Application
This guide covers how to sign your Wails applications for macOS, Windows, and Linux. Wails v3 provides built-in CLI tools for code signing, notarization, and PGP key management.
- macOS - Sign and notarize your macOS applications
- Windows - Sign your Windows executables and packages
- Linux - Sign DEB and RPM packages with PGP keys
Cross-Platform Signing Matrix
This matrix shows what you can sign from each source platform:
| Target Format | From Windows | From macOS | From Linux |
|---|---|---|---|
| Windows EXE/MSI | ✅ | ✅ | ✅ |
| macOS .app bundle | ❌ | ✅ | ❌ |
| macOS notarization | ❌ | ✅ | ❌ |
| Linux DEB | ✅ | ✅ | ✅ |
| Linux RPM | ✅ | ✅ | ✅ |
Signing Backends
Wails automatically selects the best available signing backend:
| Platform | Native Backend | Cross-Platform Backend |
|---|---|---|
| Windows | signtool.exe (Windows SDK) |
Built-in |
| macOS | codesign (Xcode) |
Not available |
| Linux | N/A | Built-in |
When running on the native platform, Wails uses the native tools for maximum compatibility. When cross-compiling, it uses the built-in signing support.
Mulai Cepat
The easiest way to configure signing is using the interactive setup wizard:
wails3 setup signing
This command:
- Walks you through configuring signing credentials for each platform
- On macOS, lists available Developer ID certificates from your keychain
- For Linux, can generate a new PGP key if you don’t have one
- Stores passwords securely in your system keychain (not in Taskfiles)
- Updates the
varssection in each platform’s Taskfile with non-sensitive config
To configure only specific platforms:
wails3 setup signing --platform darwin
wails3 setup signing --platform windows --platform linux
Manual Configuration
Alternatively, you can manually edit the platform-specific Taskfiles. Edit the vars section at the top of each file:
Edit build/darwin/Taskfile.yml:
vars:
SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)"
KEYCHAIN_PROFILE: "my-notarize-profile"
# ENTITLEMENTS: "build/darwin/entitlements.plist"Then run:
wails3 task darwin:sign # Sign only
wails3 task darwin:sign:notarize # Sign and notarize
Edit build/windows/Taskfile.yml:
vars:
SIGN_CERTIFICATE: "path/to/certificate.pfx"
# Or use thumbprint instead:
# SIGN_THUMBPRINT: "certificate-thumbprint"
# TIMESTAMP_SERVER: "http://timestamp.digicert.com"Password is retrieved from system keychain (run wails3 setup signing to configure).
Then run:
wails3 task windows:sign # Sign executable
wails3 task windows:sign:installer # Sign NSIS installer
Edit build/linux/Taskfile.yml:
vars:
PGP_KEY: "path/to/signing-key.asc"
# SIGN_ROLE: "builder" # Options: origin, maint, archive, builderPassword is retrieved from system keychain (run wails3 setup signing to configure).
Then run:
wails3 task linux:sign:deb # Sign DEB package
wails3 task linux:sign:rpm # Sign RPM package
wails3 task linux:sign:packages # Sign all packages
You can also inspect signing state from the system directly:
# List available macOS code-signing identities
security find-identity -v -p codesigning
# List PGP keys (Linux package signing)
gpg --list-keys
For interactive setup of every platform’s signing configuration, use the wizard:
wails3 setup signing
macOS Code Signing
Prerequisites
- Apple Developer Account ($99/year)
- Developer ID Application certificate
- Xcode Command Line Tools installed
Signing Identities
Check available signing identities:
security find-identity -v -p codesigning
Output:
Found 2 signing identities:
Developer ID Application: Your Company (ABCD1234) [valid]
Hash: ABC123DEF456...
Apple Development: your@email.com (XYZ789) [valid]
Hash: DEF789ABC123...Configuration
Edit build/darwin/Taskfile.yml and set the signing variables:
vars:
SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)"
KEYCHAIN_PROFILE: "my-notarize-profile"
ENTITLEMENTS: "build/darwin/entitlements.plist"| Variable | Required | Description |
|---|---|---|
SIGN_IDENTITY |
Yes | Your Developer ID (e.g., “Developer ID Application: Your Company (TEAMID)”) |
KEYCHAIN_PROFILE |
For notarization | Keychain profile name with stored credentials |
ENTITLEMENTS |
No | Path to entitlements file |
Then run:
wails3 task darwin:sign # Build, package, and sign
wails3 task darwin:sign:notarize # Build, package, sign, and notarize
Entitlements
Entitlements control what capabilities your app has access to. Wails apps typically need different entitlements for development vs production:
- Development: Requires JIT, unsigned memory, and debugging entitlements
- Production: Minimal entitlements (just network access)
Use the interactive setup wizard to generate both files:
wails3 setup entitlements
This creates:
build/darwin/entitlements.dev.plist- For development buildsbuild/darwin/entitlements.plist- For production/signed builds
Presets available:
| Preset | Description |
|---|---|
| Development | JIT, unsigned memory, debugging, network |
| Production | Network only (minimal, most secure) |
| Both | Creates both dev and production files (recommended) |
| App Store | Sandbox enabled with network and file access |
| Custom | Choose individual entitlements |
Then set ENTITLEMENTS in your Taskfile vars to point to the appropriate file.
Notarization
Apple requires all distributed apps to be notarized.
Step 1
- Store your credentials in the keychain (one-time setup). Either run
wails3 setup signing(it prompts for these values and callsnotarytoolunder the hood) or callnotarytooldirectly:
xcrun notarytool store-credentials "my-notarize-profile" \
--apple-id "your@email.com" \
--team-id "ABCD1234" \
--password "app-specific-password"
-
Set KEYCHAIN_PROFILE in your Taskfile to match the profile name above.
-
Sign and notarize your app:
wails3 task darwin:sign:notarize
- Verify notarization:
spctl --assess --verbose=2 bin/MyApp.app
Windows Code Signing
Prerequisites
- Code signing certificate (from DigiCert, Sectigo, etc.)
- For native signing: Windows SDK installed (for signtool.exe)
- For cross-platform: Just the certificate file
Configuration
Edit build/windows/Taskfile.yml and set the signing variables:
vars:
SIGN_CERTIFICATE: "path/to/certificate.pfx"
# Or use thumbprint instead:
# SIGN_THUMBPRINT: "certificate-thumbprint"
# TIMESTAMP_SERVER: "http://timestamp.digicert.com"| Variable | Required | Description |
|---|---|---|
SIGN_CERTIFICATE |
One of these | Path to .pfx/.p12 certificate file |
SIGN_THUMBPRINT |
One of these | Certificate thumbprint in Windows cert store |
TIMESTAMP_SERVER |
No | Timestamp server URL (default: http://timestamp.digicert.com) |
Then run:
wails3 task windows:sign # Build and sign executable
wails3 task windows:sign:installer # Build and sign NSIS installer
Cross-Platform Signing
Windows executables can be signed from any platform. The same Taskfile configuration and commands work on macOS and Linux.
Supported Windows Formats
| Format | Extension | Notes |
|---|---|---|
| Executables | .exe | Standard PE signing |
| Installers | .msi | Windows Installer packages |
| App Packages | .msix, .appx | Modern Windows apps |
Linux Package Signing
Linux packages (DEB and RPM) are signed using PGP/GPG keys. Unlike Windows and macOS code signing, Linux package signing proves the package came from a trusted source rather than that the code is trusted by the OS.
Prerequisites
- PGP key pair (can be generated with Wails)
Generating a PGP Key
If you don’t have a PGP key, generate one with gpg (the wails3 setup signing wizard offers to do this for you and asks the same questions):
# Interactive — the wizard will prompt for name, email, key size and expiry.
gpg --full-generate-key
# Export the key pair to ASCII-armoured files for the Taskfile to consume.
gpg --armor --export-secret-keys "your@email.com" > signing-key.asc
gpg --armor --export "your@email.com" > signing-key.pub.asc
Recommended settings: RSA 4096-bit, 1-year expiry, protected with a strong password.
Configuration
Edit build/linux/Taskfile.yml and set the signing variables:
vars:
PGP_KEY: "path/to/signing-key.asc"
# SIGN_ROLE: "builder" # Options: origin, maint, archive, builder| Variable | Required | Description |
|---|---|---|
PGP_KEY |
Yes | Path to PGP private key file |
SIGN_ROLE |
No | DEB signing role (default: builder) |
Then run:
wails3 task linux:sign:deb # Build and sign DEB package
wails3 task linux:sign:rpm # Build and sign RPM package
wails3 task linux:sign:packages # Build and sign all packages
DEB Signing Roles
For DEB packages, you can specify the signing role via SIGN_ROLE:
origin: Signature from the package originmaint: Signature from the package maintainerarchive: Signature from the archive maintainerbuilder: Signature from the package builder (default)
Cross-Platform Signing
Linux packages can be signed from any platform. The same Taskfile configuration and commands work on Windows and macOS.
Viewing Key Information
gpg --show-keys signing-key.asc
Output:
pub rsa4096 2024-01-15 [SC] [expires: 2025-01-15]
1234 5678 90AB CDEF 1234 5678 90AB CDEF 1234 5678
uid Your Name <your@email.com>Verifying Linux Packages
# Verify DEB signature
dpkg-sig --verify myapp_1.0.0_amd64.deb
# Verify RPM signature
rpm --checksig myapp-1.0.0.x86_64.rpm
Distributing Your Public Key
Users need your public key to verify packages:
# Export public key for distribution
gpg --armor --export "your@email.com" > myapp-signing.pub.asc
# Users can import it:
# For DEB (apt):
sudo apt-key add myapp-signing.pub.asc
# Or for modern apt:
sudo cp myapp-signing.pub.asc /etc/apt/trusted.gpg.d/
# For RPM:
sudo rpm --import myapp-signing.pub.asc
GitHub Actions Integration
In CI environments, passwords are provided via environment variables instead of the system keychain:
| Environment Variable | Description |
|---|---|
WAILS_WINDOWS_CERT_PASSWORD |
Windows certificate password |
WAILS_PGP_PASSWORD |
PGP key password for Linux packages |
You can also pass Taskfile variables directly:
wails3 task darwin:sign SIGN_IDENTITY="$SIGN_IDENTITY" KEYCHAIN_PROFILE="$KEYCHAIN_PROFILE"
macOS Workflow
name: Build and Sign macOS
on:
push:
tags: ['v*']
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Install Wails
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Import Certificate
env:
CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE }}
CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
run: |
echo $CERTIFICATE_BASE64 | 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 "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" build.keychain
- name: Store Notarization Credentials
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
xcrun notarytool store-credentials "notarize-profile" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_PASSWORD"
- name: Build, Sign, and Notarize
env:
SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }}
run: |
wails3 task darwin:sign:notarize \
SIGN_IDENTITY="$SIGN_IDENTITY" \
KEYCHAIN_PROFILE="notarize-profile"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: MyApp-macOS
path: bin/*.appWindows Workflow
name: Build and Sign Windows
on:
push:
tags: ['v*']
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Install Wails
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Import Certificate
env:
CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE }}
run: |
$certBytes = [Convert]::FromBase64String($env:CERTIFICATE_BASE64)
[IO.File]::WriteAllBytes("certificate.pfx", $certBytes)
- name: Build and Sign
env:
WAILS_WINDOWS_CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
wails3 task windows:sign SIGN_CERTIFICATE=certificate.pfx
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: MyApp-Windows
path: bin/*.exeCross-Platform Workflow (Linux Runner)
Sign Windows and Linux packages from a single Linux runner:
name: Build and Sign (Cross-Platform)
on:
push:
tags: ['v*']
jobs:
build-and-sign:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Install Wails
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Install Build Dependencies
run: |
sudo apt-get update
sudo apt-get install -y nsis rpm
# Import certificates
- name: Import Certificates
env:
WINDOWS_CERT_BASE64: ${{ secrets.WINDOWS_CERTIFICATE }}
PGP_KEY_BASE64: ${{ secrets.PGP_PRIVATE_KEY }}
run: |
echo "$WINDOWS_CERT_BASE64" | base64 -d > certificate.pfx
echo "$PGP_KEY_BASE64" | base64 -d > signing-key.asc
# Build and sign Windows
- name: Build and Sign Windows
env:
WAILS_WINDOWS_CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
wails3 task windows:sign SIGN_CERTIFICATE=certificate.pfx
# Build and sign Linux packages
- name: Build and Sign Linux Packages
env:
WAILS_PGP_PASSWORD: ${{ secrets.PGP_PASSWORD }}
run: |
wails3 task linux:sign:packages PGP_KEY=signing-key.asc
# Cleanup secrets
- name: Cleanup
if: always()
run: rm -f certificate.pfx signing-key.asc
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: signed-binaries
path: |
bin/*.exe
bin/*.deb
bin/*.rpmCLI Reference
wails3 setup signing
Interactive wizard to configure signing for your project.
wails3 setup signing [flags]
Flags:
--platform Platform to configure (darwin, windows, linux). Repeatable.
If omitted, auto-detects which platforms to configure from the build directory.
The wizard guides you through:
- macOS: Selecting a Developer ID certificate, configuring notarization credentials (calls
xcrun notarytool store-credentials). - Windows: Choosing between certificate file or thumbprint, setting password and timestamp server.
- Linux: Using an existing PGP key or generating a new one (calls
gpg), configuring signing role.
wails3 setup entitlements
Interactive wizard to configure macOS entitlements.
wails3 setup entitlements [flags]
Flags:
--output Output path for entitlements.plist (default: build/darwin/entitlements.plist)
Presets:
- Development: Creates
entitlements.dev.plistwith JIT, debugging, and network - Production: Creates
entitlements.plistwith minimal entitlements - Both: Creates both files (recommended)
- App Store: Creates sandboxed entitlements for Mac App Store
- Custom: Choose individual entitlements and target file
wails3 sign
Sign binaries and packages for the current or specified platform. This is a wrapper that calls the appropriate platform-specific signing task.
wails3 sign
wails3 sign GOOS=darwin
wails3 sign GOOS=windows
wails3 sign GOOS=linux
This runs the corresponding <platform>:sign task which uses the signing configuration from your Taskfile.
wails3 tool sign
Low-level command to sign a specific file directly. Used internally by the Taskfiles.
wails3 tool sign [flags]
Common Flags:
| Flag | Description |
|---|---|
--input |
Path to the file to sign |
--output |
Output path (optional, defaults to in-place) |
--verbose |
Enable verbose output |
Windows/macOS Flags:
| Flag | Description |
|---|---|
--certificate |
Path to PKCS#12 (.pfx/.p12) certificate |
--password |
Certificate password |
--timestamp |
Timestamp server URL |
macOS-Specific Flags:
| Flag | Description |
|---|---|
--identity |
Signing identity (use ‘-’ for ad-hoc) |
--entitlements |
Path to entitlements plist |
--hardened-runtime |
Enable hardened runtime (default: true) |
--notarize |
Submit for notarization |
--keychain-profile |
Keychain profile for notarization |
Windows-Specific Flags:
| Flag | Description |
|---|---|
--thumbprint |
Certificate thumbprint in Windows store |
Linux-Specific Flags:
| Flag | Description |
|---|---|
--pgp-key |
Path to PGP private key |
--pgp-password |
PGP key password |
--role |
DEB signing role (origin/maint/archive/builder) |
Inspecting signing state (native tools)
There is no wails3 signing command in v3. To inspect signing state, use the native tooling directly:
| Task | Command |
|---|---|
| List macOS code-signing identities | security find-identity -v -p codesigning |
| Store notarization credentials | xcrun notarytool store-credentials "<profile>" --apple-id … --team-id … --password … |
| Inspect a PGP key file | gpg --show-keys <key.asc> |
| Generate a PGP key pair | gpg --full-generate-key |
| Export a public key | gpg --armor --export <email> |
Troubleshooting
macOS Issues
“No Developer ID certificate found”
- Ensure your certificate is installed in the Keychain
- Check it hasn’t expired with
security find-identity -v -p codesigning - Make sure you have a “Developer ID Application” certificate (not just “Apple Development”)
“Notarization failed”
- Check the notarization log:
xcrun notarytool log <submission-id> --keychain-profile <profile> - Ensure hardened runtime is enabled
- Verify your app doesn’t include unsigned binaries
“Codesign failed”
- Make sure the keychain is unlocked:
security unlock-keychain - Check file permissions on the app bundle
Windows Issues
“Certificate not found”
- Verify the certificate path is correct
- Check the certificate password
- Ensure the certificate is valid (not expired or revoked)
“Timestamp server error”
- Try a different timestamp server:
http://timestamp.digicert.comhttp://timestamp.sectigo.comhttp://timestamp.comodoca.com
Linux Issues
“Invalid PGP key”
- Ensure the key file is in ASCII-armored format
- Check the key hasn’t expired with
gpg --show-keys <key.asc> - Verify the password is correct
“Signature verification failed”
- Ensure the public key is properly imported
- Check that the package wasn’t modified after signing