Last modified: January 24, 2026
This article is written in: πΊπΈ
This document explains how to set up macOS code signing and notarization for the Standard of Iron project.
The macOS build workflow includes automatic code signing and notarization to ensure the application can be opened on macOS without Gatekeeper warnings. This process:
.app bundle with a Developer ID Application certificateTo enable signing and notarization, you need:
.p12 formatxxxx-xxxx-xxxx-xxxx)A1B2C3D4E5)Add the following secrets to your GitHub repository:
| Secret Name | Description | How to Get Value |
MACOS_CERTIFICATE |
Base64-encoded .p12 certificate | Run: base64 -i certificate.p12 | pbcopy (copies to clipboard) |
MACOS_CERTIFICATE_PASSWORD |
Password for the .p12 file | The password you set when exporting the certificate |
MACOS_KEYCHAIN_PASSWORD |
Password for temporary keychain | Any strong random password (e.g., openssl rand -base64 32) |
APPLE_ID |
Your Apple ID email | Your Apple Developer account email |
APPLE_ID_PASSWORD |
App-specific password | The password from Step 3 (with dashes) |
APPLE_TEAM_ID |
Your Apple Developer Team ID | The 10-character code from Step 4 |
# On macOS, encode and copy to clipboard
base64 -i /path/to/certificate.p12 | pbcopy
# On Linux
base64 -w 0 /path/to/certificate.p12
When all required secrets are present:
.app is signed with your Developer IDIf secrets are not configured:
This graceful fallback allows: - Testing builds without certificates - Community contributors to build without Apple Developer accounts - Quick iterations during development
If only signing credentials are present (no notarization credentials):
If notarization fails, the script will: 1. Show the error message from Apple 2. Attempt to retrieve detailed logs 3. Exit with an error code
Common issues: - Invalid code signature: Ensure frameworks are signed before the main app - Hardened runtime violations: Add appropriate entitlements if needed - Invalid credentials: Verify Apple ID, password, and Team ID
Error: "Developer ID Application certificate not found in keychain"
Solutions: - Verify the certificate is a Developer ID Application certificate - Ensure the certificate is not expired - Check that the .p12 file contains the certificate and private key
Error: "User interaction is not allowed"
Solutions:
- Ensure MACOS_KEYCHAIN_PASSWORD secret is set
- Check that the keychain is properly unlocked in the script
GitHub Secrets are: - β Encrypted at rest - β Only exposed to GitHub Actions runners - β Never logged or exposed in outputs - β Redacted in build logs
The signing script: - Creates a temporary keychain for signing - Immediately deletes certificates after use - Cleans up keychains on completion or failure
Developer ID Application certificates: - Valid for 5 years - Must be renewed before expiration - Apple will email reminders before expiration
Remember to: - Update the certificate in GitHub Secrets before expiration - Test the new certificate before the old one expires
You can test the signing script locally:
# Set environment variables
export MACOS_CERTIFICATE="$(base64 -i certificate.p12)"
export MACOS_CERTIFICATE_PASSWORD="your-password"
export MACOS_KEYCHAIN_PASSWORD="temp-password"
export APPLE_ID="your@email.com"
export APPLE_ID_PASSWORD="xxxx-xxxx-xxxx-xxxx"
export APPLE_TEAM_ID="A1B2C3D4E5"
# Run the script
./scripts/sign-and-notarize-macos.sh build/bin/standard_of_iron.app standard_of_iron-macos.dmg
# Check code signature
codesign --verify --deep --strict --verbose=2 standard_of_iron.app
# Check Gatekeeper assessment
spctl --assess --type execute --verbose standard_of_iron.app
# Verify stapled ticket
stapler validate standard_of_iron-macos.dmg
To test the fallback behavior:
# Run without environment variables
./scripts/sign-and-notarize-macos.sh build/bin/standard_of_iron.app standard_of_iron-macos.dmg
Expected output: "macOS signing credentials not found, skipping signing and notarization"
If you encounter issues: