The complete technical guide to building, code-signing, and publishing Flutter iOS apps using cloud runners and CI/CD pipelines without owning an Apple computer.
One of the most persistent hurdles for Flutter developers working on Windows PCs is Apple’s strict requirement for macOS and Xcode to build, code-sign, and upload iOS binaries (.ipa files) to App Store Connect. If you do not own a Mac, you might think you are locked out of the Apple ecosystem. Fortunately, that is completely untrue in 2026.
In this comprehensive guide, we will walk you through the four battle-tested methods for building, signing, and releasing production Flutter iOS applications directly from your Windows development environment, complete with automated GitHub Actions workflows and certificate extraction scripts.
Why Apple Requires macOS (And How Cloud Runners Solve It) Apple requires the proprietary Xcode toolchain (clang, ibtool, codesign, altool) to compile Swift/Objective-C frameworks and execute cryptographic code-signing with your Apple Developer certificates. Windows and Linux operating systems cannot run Xcode natively. However, you do not need physical Apple hardware on your desk. By leveraging cloud-based macOS virtual machines via CI/CD runners (such as GitHub Actions or Codemagic), you can trigger automated iOS builds directly from your Windows Git commits.
Planning a Flutter Engineering project?
Book a free strategy session with our senior architects to evaluate your technical scope, UI requirements, and timeline estimates.
Method 1: Automated GitHub Actions Cloud Pipeline (Recommended) GitHub provides macOS virtual runners (`macos-14` with Apple Silicon M1/M2 virtualization) that include the latest Xcode, CocoaPods, and Flutter SDKs out of the box. Every public repository receives free build minutes, and private repositories include 2,000 monthly minutes on standard plans.
Step 1: Extract Certificates on Windows Using OpenSSL To code-sign an iOS build in a headless CI/CD environment, you need three credentials from your Apple Developer Account: 1. **Apple Distribution Certificate (.p12)** 2. **Mobile Provisioning Profile (.mobileprovision)** 3. **App Store Connect API Key (.p8)** for automated store upload If you created your CSR on Windows, use OpenSSL in Git Bash to generate your private key and export your `.p12` container: ```bash # Generate private key openssl genrsa -out apperdev_ios.key 2048 # Generate Certificate Signing Request (CSR) openssl req -new -key apperdev_ios.key -out CertificateSigningRequest.certSigningRequest -subj "/[email protected], CN=Your Name, C=US" ``` Upload this CSR to the Apple Developer Portal under **Certificates > Production > Apple Distribution**, download the generated `.cer` file, and combine them into a `.p12` file: ```bash openssl x509 -in distribution.cer -inform DER -out distribution.pem -outform PEM openssl pkcs12 -export -inkey apperdev_ios.key -in distribution.pem -out apperdev_distribution.p12 ```
Step 2: Configure GitHub Repository Secrets Encode your certificate and provisioning profile into base64 strings so they can be securely stored in GitHub Secrets without file corruption: ```bash base64 -w 0 apperdev_distribution.p12 > p12_base64.txt base64 -w 0 Apperdev_AppStore.mobileprovision > profile_base64.txt ``` In your GitHub repository, navigate to **Settings > Secrets and variables > Actions** and add: - `BUILD_CERTIFICATE_BASE64`: The base64 contents of your `.p12` file - `P12_PASSWORD`: The password you set during `.p12` export - `BUILD_PROVISION_PROFILE_BASE64`: The base64 contents of your `.mobileprovision` file - `APP_STORE_CONNECT_API_KEY`: The contents of your App Store Connect `.p8` key - `APP_STORE_KEY_ID`: Your Key ID from App Store Connect - `APP_STORE_ISSUER_ID`: Your Issuer ID (UUID format)
Step 3: Production GitHub Actions Workflow YAML Create `.github/workflows/deploy-ios.yml` in your Flutter project: ```yaml name: Build & Deploy Flutter iOS from Windows on: push: tags: - "v*" jobs: build-ios: runs-on: macos-14 steps: - name: Checkout Code uses: actions/checkout@v4 - name: Setup Java & Flutter uses: subosito/flutter-action@v2 with: flutter-version: "3.24.x" channel: "stable" cache: true - name: Install Apple Certificate & Provisioning Profile env: BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} run: | CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH security create-keychain -p "" $KEYCHAIN_PATH security set-keychain-settings -lut 21600 $KEYCHAIN_PATH security unlock-keychain -p "" $KEYCHAIN_PATH security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security set-key-partition-list -S apple-tool:,apple: -s -k "" $KEYCHAIN_PATH mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ - name: Install Dependencies run: flutter pub get - name: Build iOS IPA run: flutter build ipa --release --export-options-plist=ios/ExportOptions.plist - name: Upload to App Store Connect run: | xcrun altool --upload-app -f build/ios/ipa/*.ipa \ --type ios \ --apiKey ${{ secrets.APP_STORE_KEY_ID }} \ --apiIssuer ${{ secrets.APP_STORE_ISSUER_ID }} ```
Method 2: Codemagic Dedicated Mobile CI/CD If you prefer a visual GUI over configuring raw GitHub Actions scripts, **Codemagic** is purpose-built for Flutter. It connects directly to your App Store Connect account via API and automatically handles certificate generation, code signing, and TestFlight distribution without requiring a single command-line step.
Method 3: Cloud macOS VPS (MacinCloud / AWS EC2 Mac) If you need interactive access to Xcode (e.g. to test with the iOS Simulator or debug native CocoaPods podfile issues), you can rent remote cloud Mac instances starting from $20/month via services like MacinCloud, AWS EC2 Mac Instances, or Scaleway. You connect via Remote Desktop Protocol (RDP) or VNC directly from your Windows machine.
Method 4: Partner with a Founder-Led Mobile Studio If navigating code signing, push notification entitlement certificates, and App Store review guidelines feels overwhelming, partner with a specialized studio. At Apperdev, we handle full build orchestration, TestFlight distribution, and App Store approval for founders worldwide. Explore our [App QA & Store Publishing services](/services/qa-store-publishing) or [hire a dedicated Flutter developer](/hire-flutter-developer).
“You do not need to spend $2,000 on a MacBook Pro just to sign and distribute a Flutter iOS binary to the Apple App Store.”
Ready to build your next mobile app?
From initial product strategy and UI/UX design systems to high-performance Flutter & React Native engineering.
Start a conversation with our team ↗Frequently Asked Questions
Do I still need an Apple Developer Account if I build from Windows?
Yes. You still need an active Apple Developer Program membership ($99/year) to generate provisioning profiles, certificates, and access App Store Connect.
Can I test an iOS app on my physical iPhone from a Windows PC?
Yes. You can distribute internal builds to your iPhone via Apple TestFlight using the automated cloud pipeline described in this guide, or connect your iPhone to a free cloud service.
Will Apple know or care that the app was compiled in a cloud runner?
No. The compiled IPA produced by a macOS GitHub Actions runner is 100% indistinguishable from a build compiled on a physical MacBook Pro.

