Open Source
Build and Sign iOS Apps Without a Mac
By DI Solutions
Developer


ios-builder is a Go command-line tool that lets you build, sign and hot-reload iOS apps from Windows or Linux. It generates a GitHub Actions workflow targeting macOS runners, dispatches the build, waits, and drops the finished IPA into your dist/ folder.
Of everything in this series, this is the one most likely to change how a Windows-based team works on Monday morning.
Key takeaways
- The build still runs on macOS — you just do not own the Mac. It is a GitHub Actions runner, billed by the minute.
- Code signing genuinely does not need a Mac. The certificate request and the
.p12are cryptography, and the tool does both locally. - Six frameworks detected automatically from the folder layout — Swift, React Native, ejected Expo, Flutter, Kotlin Multiplatform, Cordova/Ionic.
- Hot reload for Flutter and React Native against a real device. Kotlin Multiplatform cannot, and the reason is architectural.
- The economics are the real constraint: about 15–20 free builds a month, because macOS minutes bill at ten times.
- Apple's requirements are untouched. You still need a paid developer account.
Why is this such a persistent problem?
Because Xcode only runs on macOS, and Xcode is the only thing that can compile and sign an iOS app. Every cross-platform team eventually collides with that.
Picture a typical agency setup. Six developers on Windows, building a React Native app for a client. Five of them can do every piece of the work — components, state, API integration, Android builds, tests — and then the iOS build lands on the one person with a MacBook. That person becomes a queue. Every demo, every TestFlight upload, every "can you check this on an iPhone" goes through them, and their holiday becomes a project risk.
The usual fixes are all purchases. Buy Macs for everyone. Rent a Mac mini. Pay for a hosted CI service. Each is defensible, and each turns a workflow annoyance into a line item.
Then there is signing, which has its own folklore. Almost everyone believes you need Keychain Access on a Mac to produce a certificate signing request and a .p12. That belief is wrong, and it is the most useful thing in this post.
How does ios-builder work?
- Detect the project.
builder initinspects the directory structure and works out which framework it is looking at, then generates the Actions workflow for it. - Dispatch the build.
builder ios buildtriggers that workflow on a macOS runner, polls it, and downloads the IPA to./dist/. From your side it is one command that takes a few minutes. - Handle signing locally.
builder signing csrgenerates a private key and certificate signing request on your machine. You upload the CSR to Apple, download the issued certificate, andbuilder signing p12assembles the bundle.builder signing setuppushes both into GitHub secrets so the runner can sign with them. - Iterate on a device.
builder dev flutterwatches your Dart files and triggers hot reload on a connected device;builder dev rndoes the same for React Native and starts Metro if it is not running.
The framework detection table is worth internalising, because it is entirely convention-based:
| Framework | iOS path | Hot reload |
|---|---|---|
| Native iOS / Swift | Repository root | No |
| React Native | ios/ | Yes, via Metro |
| Expo (ejected) | ios/ | Yes, via Metro |
| Flutter | ios/ | Yes |
| Kotlin Multiplatform | iosApp/ | No — compiled to a native framework at build time |
| Cordova / Ionic | platforms/ios/ | No |
Getting to a first build
Install via Homebrew, the install script, or by downloading builder.exe from the releases page on Windows. Then three commands:
builder auth github # GitHub authentication
builder init # Workflow setup
builder ios build # Trigger build and download IPAIf you want to check the pipeline before dealing with Apple at all, builder ios build --unsigned skips signing entirely. That is the right first step: prove the build works, then fight the certificates.
The economics, stated plainly
This is where the plan meets reality. GitHub's free tier gives 2,000 Actions minutes a month, but macOS runners bill at a ten times multiplier. That leaves roughly 200 effective macOS minutes — about fifteen to twenty iOS builds.
Fifteen builds a month is comfortable for a project in maintenance. It is nothing during an active sprint where you build several times a day. So the honest positioning is: this tool removes the hardware requirement and replaces it with a metered one.
That is still usually a better deal. Actions minutes are a variable cost you can turn off; a Mac mini is capital, and a MacBook for every developer is a serious number. But go in with build discipline — build on merge, not on every push — rather than assuming free means unlimited.
Alternatives worth knowing
- Expo EAS Build — if you are on Expo, this is the path of least resistance and it is very good. Paid, hosted, managed. You give up transparency and gain a lot of time.
- Codemagic or Bitrise — mature mobile CI with proper dashboards, test device farms and store submission built in. More expensive, considerably more capable.
- Hand-written GitHub Actions — exactly what ios-builder generates, without the tool. If you already have a DevOps person and want no extra dependency, write the workflow once and keep it.
- One shared Mac mini — unfashionable but effective. A single machine as a build server, accessed remotely, is often cheaper than a year of hosted CI and gives you a real Xcode when something goes wrong.
Limitations to plan around
- The macOS minute multiplier is the hard ceiling. Plan your build cadence around it.
- Kotlin Multiplatform has no hot reload, and it may need an explicit JDK version set in the config file before it builds at all.
- Device features need the MobAI app, and simulator sharing needs a paid subscription. The open-source CLI and the commercial product are intertwined.
- React Native hot reload needs the same WiFi as the Metro host. Fine in an office, awkward for remote teams.
- No Xcode means no Xcode debugging. When a build fails for an Xcode-specific reason, you are reading CI logs instead of using Instruments. Keep one Mac somewhere for the bad days.
Conclusion
ios-builder does not defeat Apple's platform requirements. It relocates them — from hardware you buy to minutes you rent, and from a person's desk to a pipeline anyone can trigger.
For a Windows-based team shipping React Native or Flutter, that is the difference between one bottleneck and none. And the signing insight is worth the read on its own: the certificate dance never needed a Mac. It just needed someone to say so.
Shipping mobile apps from a Windows team?
DI Solutions builds React Native and Flutter apps and sets up the pipelines that get them onto real devices and into the stores, without a Mac on every desk. Talk to our mobile team about your build setup.
Reference links
Frequently Asked Questions (FAQs)
Can you really build an iOS app without a Mac?
You can build one without owning a Mac, but the build itself still happens on macOS — on a GitHub Actions macOS runner. ios-builder is a Go command-line tool that generates the workflow, dispatches the build, waits for it and downloads the resulting IPA to your machine.
Do you need a Mac to create an iOS signing certificate?
No, and this is the most surprising part. A certificate signing request and the resulting .p12 bundle are ordinary cryptography, not something only Keychain Access can produce. ios-builder generates the key and CSR locally, assembles the .p12 after Apple issues the certificate, and uploads both as GitHub secrets.
Which frameworks does ios-builder support?
Six, detected automatically from the directory structure: native Swift at the repository root, React Native and ejected Expo in ios/, Flutter in ios/, Kotlin Multiplatform in iosApp/, and Cordova or Ionic in platforms/ios/.
How many free iOS builds do you get?
Roughly fifteen to twenty a month on GitHub's free tier. The allowance is 2,000 minutes, but macOS runners bill at a ten times multiplier, which leaves about 200 effective macOS minutes. Beyond that you are paying for Actions minutes.
Does ios-builder support hot reload?
For Flutter and React Native, yes — it watches your files and triggers hot reload against a device connected through the MobAI app, starting the Metro bundler for React Native if it is not already running. Kotlin Multiplatform has no hot reload, because shared Kotlin is compiled into a native framework at build time.
Do you still need an Apple Developer account?
Yes. ios-builder removes the Mac requirement, not Apple's requirements. You still need a paid Apple Developer account to sign an app for real devices and to submit anything to the App Store.
Is ios-builder free?
The CLI is open source under the MIT licence. Building and signing use your own GitHub Actions minutes. Simulator sharing and the on-device development features require the MobAI app, and simulator sharing needs a paid MobAI subscription.




