Code Signing
このコンテンツはまだ日本語訳がありません。
Code Signing Your Application
Section titled “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
Section titled “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
Section titled “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.
Quick Start
Section titled “Quick Start”The easiest way to configure signing is using the interactive setup wizard:
wails3 setup signingThis 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 darwinwails3 setup signing --platform windows --platform linuxManual Configuration
Section titled “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 onlywails3 task darwin:sign:notarize # Sign and notarizeEdit 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 executablewails3 task windows:sign:installer # Sign NSIS installerEdit 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 packagewails3 task linux:sign:rpm # Sign RPM packagewails3 task linux:sign:packages # Sign all packagesYou can also inspect signing state from the system directly:
# List available macOS code-signing identitiessecurity find-identity -v -p codesigning
# List PGP keys (Linux package signing)gpg --list-keysFor interactive setup of every platform’s signing configuration, use the wizard:
wails3 setup signingmacOS Code Signing
Section titled “macOS Code Signing”Prerequisites
Section titled “Prerequisites”- Apple Developer Account ($99/year)
- Developer ID Application certificate
- Xcode Command Line Tools installed
Signing Identities
Section titled “Signing Identities”Check available signing identities:
security find-identity -v -p codesigningOutput:
Found 2 signing identities:
Developer ID Application: Your Company (ABCD1234) [valid] Hash: ABC123DEF456...
Apple Development: [email protected] (XYZ789) [valid] Hash: DEF789ABC123...Configuration
Section titled “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 signwails3 task darwin:sign:notarize # Build, package, sign, and notarizeEntitlements
Section titled “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 entitlementsThis 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
Section titled “Notarization”Apple requires all distributed apps to be notarized.
-
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:Terminal window xcrun notarytool store-credentials "my-notarize-profile" \--team-id "ABCD1234" \--password "app-specific-password" -
Set KEYCHAIN_PROFILE in your Taskfile to match the profile name above.
-
Sign and notarize your app:
Terminal window wails3 task darwin:sign:notarize -
Verify notarization:
Terminal window spctl --assess --verbose=2 bin/MyApp.app
Windows Code Signing
Section titled “Windows Code Signing”Prerequisites
Section titled “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
Section titled “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 executablewails3 task windows:sign:installer # Build and sign NSIS installerCross-Platform Signing
Section titled “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
Section titled “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
Section titled “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
Section titled “Prerequisites”- PGP key pair (can be generated with Wails)
Generating a PGP Key
Section titled “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.Recommended settings: RSA 4096-bit, 1-year expiry, protected with a strong password.
Configuration
Section titled “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 packagewails3 task linux:sign:rpm # Build and sign RPM packagewails3 task linux:sign:packages # Build and sign all packagesDEB Signing Roles
Section titled “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
Section titled “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
Section titled “Viewing Key Information”gpg --show-keys signing-key.ascOutput:
pub rsa4096 2024-01-15 [SC] [expires: 2025-01-15] 1234 5678 90AB CDEF 1234 5678 90AB CDEF 1234 5678uid Your Name <[email protected]>Verifying Linux Packages
Section titled “Verifying Linux Packages”# Verify DEB signaturedpkg-sig --verify myapp_1.0.0_amd64.deb
# Verify RPM signaturerpm --checksig myapp-1.0.0.x86_64.rpmDistributing Your Public Key
Section titled “Distributing Your Public Key”Users need your public key to verify packages:
# Export public key for distribution
# 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.ascGitHub Actions Integration
Section titled “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
Section titled “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
Section titled “Windows 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)
Section titled “Cross-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
Section titled “CLI Reference”wails3 setup signing
Section titled “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
Section titled “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
Section titled “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 signwails3 sign GOOS=darwinwails3 sign GOOS=windowswails3 sign GOOS=linuxThis runs the corresponding <platform>:sign task which uses the signing configuration from your Taskfile.
wails3 tool sign
Section titled “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)
Section titled “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
Section titled “Troubleshooting”macOS Issues
Section titled “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
Section titled “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
Section titled “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