Many teams encounter a problem when automating iOS releases: the IPA is built on a macOS node, but they don’t want to rely on Xcode for the upload process.
Reasons include:

  1. GUI is not suitable in CI environments
  2. Manual operations are too heavy for multi-project uploads
  3. Upload behavior can change after Xcode updates
  4. Linux servers are better suited for running release scripts

Thus, a typical architecture emerges: macOS handles building, Linux handles uploading.
This article focuses on how to automatically upload IPA to App Store Connect from a Linux environment and truly integrate the upload action into the automation workflow.

Decouple Build and Upload

When first setting up CI, many people put IPA generation and App Store upload in the same stage. In reality, these two tasks can be completely decoupled.

The build stage handles archiving, signing, and exporting the IPA, usually on macOS.
The upload stage handles metadata generation, App Store Connect upload, and build submission. This stage can be entirely placed on Linux.

Linux is Better Suited as an Upload Node

If a project has moved to daily builds, multi-environment releases, automated testing, and multi-person collaboration,
Linux advantages become clear.

For example:

Scenario Linux Advantage
Jenkins Easy deployment
Docker Easy isolation
GitLab CI Mature Runner
GitHub Actions Easy scripting

GUI upload is hard to maintain in these environments. In real projects, it’s common that:

  • macOS node runs flutter build ipa or xcodebuild archive to generate app.ipa
  • Linux node receives the IPA, uploads to App Store Connect, and outputs logs

What is Needed for Linux Upload

The upload stage requires:

Item Purpose
IPA file Upload payload
Apple ID Developer account
App-Specific Password Upload authentication
Upload tool Submit the IPA

Obtain App-Specific Password

Do not use your Apple login password. You need to create an App-Specific Password in your Apple ID security settings. The upload tool will use this password for authentication.

Upload Tool in Linux Environment

Here we take AppUploader (Happy Upload) CLI as an example.

The Linux version is located at runtime/appuploader_cli. First, grant permissions: chmod +x appuploader_cli

Execute Upload Command

Direct upload:

./appuploader_cli upload \
-f app.ipa \
-u user@example.com \
-p xxxx-xxxx-xxxx-xxxx \
--type ios

Alternatively:

./appuploader_cli --upload-app \
-f app.ipa \
-u user@example.com \
-p xxxx-xxxx-xxxx-xxxx \
--type ios

What happens during the upload? The CLI tool will:

  1. Automatically parse IPA information: read Bundle ID, Version, Build Number
  2. Generate metadata: including AppStoreInfo.plist, no manual creation needed
  3. Submit to App Store Connect: after successful upload, Apple begins processing the build

Complete CI Example

Below is a GitLab CI scenario.
Build stage (macOS Runner):

build_ios:
  script:
    - flutter build ipa

Generates:

build/ios/ipa/app.ipa

Upload Stage (Linux Runner)

upload_ios:
  script:
    - chmod +x appuploader_cli
    - ./appuploader_cli upload \
      -f build/ios/ipa/app.ipa \
      -u $APPLE_ID \
      -p $APP_PASSWORD \
      --type ios

Where to Check Results After Upload

Go to App Store Connect → TestFlight. If the upload was successful, the build should appear within a few minutes. If not, check the following:

Check Item Content
Build Number Is it incremented?
Bundle ID Does it match?
IPA Signing Is it App Store type?
App-Specific Password Is it valid?

Project Types Suitable for Linux Automated Upload

The following project types are well-suited:

Type Scenario
Flutter Automated build
React Native CI release
Unity Cloud build
uni-app Upload after cloud packaging
HBuilderX Automatic IPA submission

Now many teams adopt:

Task Tool
Development Flutter / RN
Packaging macOS
Upload Linux CLI
Review Mgmt App Store Connect

This way:

  • Linux handles automation
  • macOS only handles compilation
  • Release process is easier to maintain

Automated IPA upload to App Store Connect from Linux essentially shifts the iOS release process from GUI to scripting. Once the IPA is generated, the upload can be completed independently via CLI.