# iOS Code Signing Guide **Author**: Matthew Raymer **Date**: 2025-11-12 **Status**: Active ## Overview iOS apps require code signing to run on devices or simulators. This guide explains how to handle signing for different scenarios. ## Signing Scenarios ### 1. Simulator Builds (Development) **For simulator builds, signing can be disabled:** ```bash xcodebuild -workspace App.xcworkspace \ -scheme App \ -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 15' \ CODE_SIGN_IDENTITY='' \ CODE_SIGNING_REQUIRED=NO \ CODE_SIGNING_ALLOWED=NO \ clean build ``` **Why this works:** - Simulator doesn't require valid code signatures - Faster builds (no signing overhead) - No need for Apple Developer account ### 2. Device Builds (Development) **For physical devices, you need proper signing:** #### Option A: Automatic Signing (Recommended) 1. **Open Xcode project:** ```bash open App.xcworkspace ``` 2. **Configure in Xcode:** - Select project in navigator - Select target "App" - Go to "Signing & Capabilities" tab - Check "Automatically manage signing" - Select your Team (Apple Developer account) - Xcode will create provisioning profile automatically 3. **Build from command line:** ```bash xcodebuild -workspace App.xcworkspace \ -scheme App \ -sdk iphoneos \ -configuration Debug \ -destination 'generic/platform=iOS' \ DEVELOPMENT_TEAM="YOUR_TEAM_ID" \ CODE_SIGN_STYLE=Automatic \ clean build ``` #### Option B: Manual Signing 1. **Get your Team ID:** ```bash # List available teams security find-identity -v -p codesigning ``` 2. **Create provisioning profile** (via Apple Developer Portal or Xcode) 3. **Build with explicit signing:** ```bash xcodebuild -workspace App.xcworkspace \ -scheme App \ -sdk iphoneos \ -configuration Debug \ -destination 'generic/platform=iOS' \ DEVELOPMENT_TEAM="YOUR_TEAM_ID" \ CODE_SIGN_STYLE=Manual \ PROVISIONING_PROFILE_SPECIFIER="Your Profile Name" \ CODE_SIGN_IDENTITY="iPhone Developer" \ clean build ``` ### 3. Command-Line Build Scripts **Update build scripts to handle both scenarios:** ```bash #!/bin/bash # Detect if building for simulator or device SDK="${1:-iphonesimulator}" DESTINATION="${2:-'platform=iOS Simulator,name=iPhone 15'}" if [ "$SDK" = "iphonesimulator" ]; then # Simulator: Disable signing xcodebuild -workspace App.xcworkspace \ -scheme App \ -sdk "$SDK" \ -destination "$DESTINATION" \ CODE_SIGN_IDENTITY='' \ CODE_SIGNING_REQUIRED=NO \ CODE_SIGNING_ALLOWED=NO \ clean build else # Device: Use automatic signing xcodebuild -workspace App.xcworkspace \ -scheme App \ -sdk "$SDK" \ -configuration Debug \ -destination 'generic/platform=iOS' \ CODE_SIGN_STYLE=Automatic \ DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM:-}" \ clean build fi ``` ## Common Signing Issues ### Issue 1: "No signing certificate found" **Solution:** ```bash # Check available certificates security find-identity -v -p codesigning # If none found, create one in Xcode: # Xcode > Preferences > Accounts > Select Team > Download Manual Profiles ``` ### Issue 2: "Provisioning profile not found" **Solution:** ```bash # List provisioning profiles ls ~/Library/MobileDevice/Provisioning\ Profiles/ # Or use automatic signing (recommended) # Xcode will create profiles automatically ``` ### Issue 3: "Code signing is required for product type" **Solution:** - For simulator: Add `CODE_SIGNING_REQUIRED=NO` - For device: Configure signing in Xcode or provide `DEVELOPMENT_TEAM` ### Issue 4: "Bundle identifier conflicts" **Solution:** - Change bundle identifier in `Info.plist`: ```xml CFBundleIdentifier com.yourcompany.yourapp ``` - Or use unique identifier for test apps ## Project Configuration ### Automatic Signing (Recommended) In Xcode project settings (`project.pbxproj` or Xcode UI): ``` CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = YOUR_TEAM_ID; ``` ### Manual Signing ``` CODE_SIGN_STYLE = Manual; CODE_SIGN_IDENTITY = "iPhone Developer"; PROVISIONING_PROFILE_SPECIFIER = "Your Profile Name"; ``` ## Environment Variables **Set these for command-line builds:** ```bash # For device builds export DEVELOPMENT_TEAM="YOUR_TEAM_ID" export CODE_SIGN_STYLE="Automatic" # For simulator builds (optional) export CODE_SIGNING_REQUIRED="NO" export CODE_SIGNING_ALLOWED="NO" ``` ## Quick Reference ### Simulator Build (No Signing) ```bash xcodebuild ... \ CODE_SIGN_IDENTITY='' \ CODE_SIGNING_REQUIRED=NO \ CODE_SIGNING_ALLOWED=NO ``` ### Device Build (Automatic Signing) ```bash xcodebuild ... \ CODE_SIGN_STYLE=Automatic \ DEVELOPMENT_TEAM="YOUR_TEAM_ID" ``` ### Device Build (Manual Signing) ```bash xcodebuild ... \ CODE_SIGN_STYLE=Manual \ CODE_SIGN_IDENTITY="iPhone Developer" \ PROVISIONING_PROFILE_SPECIFIER="Profile Name" ``` ## Testing Signing Configuration **Test if signing works:** ```bash # Check code signature codesign -dv --verbose=4 /path/to/App.app # Verify signature codesign --verify --verbose /path/to/App.app # Check entitlements codesign -d --entitlements - /path/to/App.app ``` ## Troubleshooting ### Check Current Signing Status ```bash # In Xcode project directory xcodebuild -showBuildSettings -workspace App.xcworkspace -scheme App | grep CODE_SIGN ``` ### Clean Derived Data ```bash # Sometimes signing issues are cached rm -rf ~/Library/Developer/Xcode/DerivedData ``` ### Reset Signing in Xcode 1. Open project in Xcode 2. Select target 3. Signing & Capabilities tab 4. Uncheck "Automatically manage signing" 5. Re-check "Automatically manage signing" 6. Select team again ## Best Practices 1. **Use Automatic Signing** for development (easiest) 2. **Disable signing for simulator** builds (faster) 3. **Use unique bundle IDs** for test apps 4. **Keep certificates updated** in Keychain 5. **Use environment variables** for team IDs in CI/CD ## References - [Apple Code Signing Guide](https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/) - [Xcode Signing Documentation](https://developer.apple.com/documentation/xcode/managing-your-team-s-signing-assets) - [Capacitor iOS Setup](https://capacitorjs.com/docs/ios/configuration)