Why does my iOS VPN app with a Network Extension fail to build on Codemagic?
Last updated: August 4, 2026
Context
When building an iOS VPN app that includes a Network Extension target (e.g., using WireGuard), you may encounter several issues, including:
Provisioning profile not found for the
.network-extensionbundle IDBuild failures related to the WireGuard Go bridge (
WireGuardGoBridgeiOS) or Swift Package Manager manifest version mismatchesArchive errors mentioning missing headers such as
u_int16_tor PCM compilation failures
Answer
There are several distinct issues that can affect this type of build. Work through each one as applicable:
1. Fix the Swift Package Manager manifest version
If your build fails at xcodebuild -showBuildSettings with errors like 'v12' is unavailable or 'v15' is unavailable in your Vendor/wireguard-apple/Package.swift, the manifest's swift-tools-version is too low. Platform targets such as .macOS(.v12) and .iOS(.v15) require Swift tools version 5.5 or higher.
Fix: Open Vendor/wireguard-apple/Package.swift and ensure the first line reads:
// swift-tools-version:5.5Commit and push the change, then re-run the build.
2. Set up code signing for multiple bundle IDs (main app + Network Extension)
A provisioning profile existing in the Apple Developer Portal is not enough on its own — it must be fetched onto the build machine. The wildcard match on com.example.app.* only picks up profiles already available to the build; it will not automatically provision the extension target.
The recommended approach is to let Codemagic fetch or create both profiles at build time using the App Store Connect integration. Follow these steps:
Generate a certificate private key on your local machine:
ssh-keygen -t rsa -b 2048 -m PEM -f ~/Desktop/ios_distribution_private_key -q -N ""Open the generated
ios_distribution_private_keyfile, copy its entire contents (including the-----BEGIN RSA PRIVATE KEY-----and-----END RSA PRIVATE KEY-----tags), and save it as an environment variable namedCERTIFICATE_PRIVATE_KEYinside a group calledcode-signingin Codemagic.Remove any manual
ios_signingblock from yourcodemagic.yaml:# Remove this block: environment: ios_signing: distribution_type: app_store bundle_identifier: com.example.appAdd the App Store Connect integration reference to your workflow. Go to Codemagic app → Teams → General settings → Team integrations → Developer Portal → Manage Keys and copy your API key reference name. Then update your
codemagic.yaml:ios-workflow: name: iOS Workflow max_build_duration: 120 instance_type: mac_mini_m2 environment: groups: - code-signing vars: BUNDLE_ID: com.example.app integrations: app_store_connect: Your API Key NameAdd the following scripts at the top of your scripts section to initialize the keychain, fetch signing files, and apply profiles:
scripts: - name: Set up keychain script: keychain initialize - name: Fetch signing files script: | app-store-connect fetch-signing-files "$BUNDLE_ID" \ --type IOS_APP_STORE \ --create - name: Set up signing certificate script: keychain add-certificates - name: Set up code signing settings on Xcode project script: xcode-project use-profiles # other scripts go hereReferring to the main bundle ID is generally sufficient — Codemagic will match and apply the correct profiles for associated extension targets.
3. Fix WireGuard Go bridge build errors (missing headers)
If the archive fails with errors referencing WireGuardGoBridgeiOS, PCM compilation failures, or a missing u_int16_t type, this is caused by a missing #include <sys/types.h> in the WireGuard-Apple package source.
Fix: Add the missing include to the relevant WireGuard-Apple source file(s). Check whether you have already applied this fix locally and forgotten to push it to your repository. For reference, see:
Once the fix is committed and pushed, re-run the build on Codemagic.