Published by Linux Stewards · Last reviewed 23 August 2026

How We Can Build iPhone and Android Apps from Linux with React Native and Expo EAS

5 min readMobile Apps

A common assumption is that you need a Mac to build iPhone apps. In practice, a modern cross-platform toolchain lets us develop and build iOS and Android apps from a Linux workstation, using cloud services for the Apple-specific signing and build steps. This is the technical backbone of our mobile work.

The Linux development workstation

Linux is a natural development environment, and it is where we are most at home. The constraint is that Apple’s official build and signing tooling is macOS-only. We work around that constraint with a cross-platform framework and a cloud build service, rather than pretending the constraint does not exist.

React Native and Expo

React Native lets one codebase produce both iOS and Android apps. Expo layers tooling on top — a development runtime, a build service, and submission tools — that removes much of the native configuration pain and keeps the workflow reliable.

A shared codebase, when appropriate

For apps that are mostly business logic, forms, data and screens, a single React Native codebase is genuinely efficient: one feature written once runs on both platforms. That is the case we reach for most often.

Why cross-platform is not automatically right

Cross-platform is a trade-off, not a default. If an app depends heavily on platform-specific behaviour, unusual hardware, or a highly bespoke native experience, a shared codebase can become a liability. We choose the approach from the requirements, not from habit.

EAS Build

EAS (Expo Application Services) Build runs the build in the cloud. For Android it produces an Android App Bundle (AAB); for iOS it produces an IPA. Because the iOS build runs on Apple-managed cloud infrastructure, it handles the macOS-only parts for us.

Cloud signing

EAS manages certificates and provisioning profiles. For iOS it can handle the signing certificates and profiles through your Apple developer account; for Android it integrates with Google Play app signing. This is the step that most often goes wrong by hand, so doing it through a managed pipeline is a significant reliability win.

EAS Submit

EAS Submit uploads the finished build to the right place — App Store Connect for iOS, Play Console for Android — and can automate TestFlight or Play testing-track submission as part of the same flow.

App Store Connect and TestFlight

From the cloud-built IPA we configure the App Store Connect record and TestFlight beta, using the customer’s Apple developer account. Apple’s review still applies; the toolchain removes the mechanical steps, not the review.

Google Play

The AAB goes to Play Console, where we configure testing tracks and the store listing, again under the customer’s developer account. Google’s verification and review requirements still apply.

CI/CD

The whole flow — code, build, sign, submit — can run from a continuous-integration pipeline. Committing a change can trigger a new build and a TestFlight or Play testing-track upload, which makes updates a repeatable process instead of a manual chore.

Secrets and credentials principles

Signing keys and provider credentials are secrets. We keep them out of source control, scope them to the minimum needed, and store them in a secret store or the platform’s own credential system. We never ask customers to hand over a personal account password; Apple and Google both support delegated access.

Limitations

The shared-codebase approach has real limits: it will not be the best fit for every app, and Apple’s own submission workflow still requires an Apple developer account. We are upfront about which projects fit the cross-platform lane and which do not.

Native modules

When an app needs functionality with no maintained Expo/React Native module, you can write a native module. That reintroduces platform-specific code, so we treat it as a deliberate decision with a cost attached rather than something to reach for casually.

When Swift/Kotlin or native work is preferable

For a heavily platform-specific experience — deep integration with iOS or Android APIs, unusual hardware, or a requirement that the app feel perfectly native on one platform — a native Swift/SwiftUI or Kotlin build can be the better engineering choice. We recommend it honestly when that is the case.

When Flutter may be considered

Flutter is a legitimate cross-platform alternative with its own strengths. When a project’s requirements or an existing codebase point that way, we consider it on its merits rather than dismissing it. The choice is driven by the project, not the framework we happen to reach for first.

Release ownership stays with the client

The app is published through the customer’s developer accounts — Apple and Google — using delegated access where supported. We never take ownership of the customer’s store presence merely to make onboarding easier.

Development builds for testing

During development we use development builds — builds installed on a device or simulator that include the native project so new native code can be tested, not just JavaScript. This is the difference between a quick reload in a simulator and actually proving the app works on a real phone before release.

Over-the-air updates

EAS Update can push JavaScript updates to an already-installed app without a new store build or review. That is genuinely useful for small, JS-only fixes and experiments. It is not a substitute for a full store release: any change to native code, permissions, or app configuration still requires a new build through the store.

Environment variables and configuration

Configuration such as API endpoints and feature flags lives in the project configuration and EAS environment variables rather than hard-coded in source. Secrets are kept in a secret store, scoped to the environment, and never committed. This keeps development, testing and production builds clearly separated.

A practical build workflow

  1. 1Write the app against the shared React Native codebase.
  2. 2Run and test locally (and in a development build on a device).
  3. 3Trigger a cloud build — an Android AAB and an iOS IPA.
  4. 4Submit the AAB to Play testing and the IPA to TestFlight.
  5. 5Run beta testing, fix issues, and repeat.
  6. 6Promote the approved build to production in each store.

What we can and cannot promise

We can develop, test, prepare builds, configure signing, deliver betas and prepare submissions. Final App Store and Google Play acceptance is decided by Apple and Google respectively, and no responsible developer guarantees it.

Need a hand with this?

Tell us what the app should do. We confirm the scope and price before work begins.

Request a Quick Check