I thought Android CI/CD would be the easy part.
After all, it works perfectly on GitHub Actions.So I tried to self-host it using Gitea.
That’s where things started breaking.
Context
In my previous posts, I’ve been experimenting heavily with Lima VMs to create isolated development environments.
- Separate environments per project
- No dependency conflicts
- Full control over provisioning
It worked surprisingly well.
I even managed to:
- Run self-hosted CI/CD using Gitea Actions
- Spin up a macOS runner for iOS builds
- Automate
xcodebuildand generate IPAs
At that point, I thought:
“If I can make iOS work… Android should be easy.”
The Plan
I’m currently building a personal app using:
- React Native
- Expo
I already have another app with the same stack running on GitHub Actions — no issues at all. Smooth builds, predictable pipelines.
So the idea was simple:
Reuse the same workflow… but run it on my own infrastructure.

Photo by Ferenc Almasi on Unsplash
Attempt #1 — Linux ARM + Docker (Lima VM)
Since I’m on an Apple Silicon Mac, I started with:
- Ubuntu (ARM) VM via Lima
- Docker-based Gitea runner
This setup worked well for other projects.
But for React Native?
❌ It failed.
The error wasn’t immediately clear, but one thing kept popping up:
Hermes
Attempt #2 — Manual Environment Setup
I thought maybe Docker was the issue.
So I went manual:
- Installed JDK
- Installed Android SDK
- Installed Node.js
- Configured environment variables
After hours of setup…
❌ Same failure.

Photo by Vitaly Gariev on Unsplash
💡 First Realization
Setup ≠ Compatibility
Just because you can install everything correctly…
doesn’t mean everything will actually work together.
The Breakthrough (and the Wall)
After digging deeper, I found the real issue:
Hermes does not support Linux ARM.
And suddenly everything made sense.
Other people were hitting the same wall:
- https://github.com/facebook/hermes/issues/995
- https://github.com/facebook/react-native/issues/46504
- https://github.com/facebook/react-native/issues/39814
💡 Second Realization
Mobile tooling is tightly coupled to platform constraints.
This isn’t just “Node + build tools”.
You’re dealing with:
- Native engines (Hermes)
- Platform-specific binaries
- Architecture limitations (ARM vs x86)
Attempt #3 — “Let’s Use My Homelab”
Okay. If ARM is the problem…
Let’s switch to x86.
I tried running the build on my homelab:
- Old Intel MacBook Pro
- 8GB RAM
- Running services like Jellyfin
What could go wrong?
💥 Everything.
The server crashed due to memory exhaustion.
💡 Third Realization
Infrastructure matters more than correctness.
Even if your setup is “technically correct”…
If your hardware can’t handle it, it doesn’t matter.
Attempt #4 — x86 VM via QEMU (Back to Lima)
Back to my Mac.
This time:
- Ubuntu x86 VM
- Running via QEMU emulation
And finally…
✅ It runs.
But there’s a catch.
⏳ It’s slow.
Like… 40+ minutes per build slow.

Photo by John Moeses Bauan on Unsplash
💡 Fourth Realization
Emulation works — but at a cost.
You can force compatibility…
But you pay for it in:
- Performance
- Time
- Developer experience
The Bigger Picture
At this point, I had to stop and ask:
“Why does this work so easily on GitHub Actions?”
🧠 Insight #1 — Cloud CI Hides the Hard Parts
When you use platforms like GitHub Actions:
- You don’t think about CPU architecture
- You don’t manage SDK installations
- You don’t deal with compatibility issues
Because they already solved it.
You’re not just using CI/CD.
You’re using pre-solved infrastructure.
🧠 Insight #2 — Mobile CI/CD Is Not Platform-Agnostic
Backend CI/CD is relatively straightforward.
Mobile?
Not even close.
You’re tied to:
- OS constraints (macOS for iOS)
- CPU architecture (ARM vs x86)
- Vendor tooling (Android SDK, Hermes, etc.)
🧠 Insight #3 — Self-Hosting Means Owning Everything
When you self-host CI/CD, you’re not just replacing GitHub Actions.
You’re taking ownership of:
- Environment provisioning
- Toolchain compatibility
- Hardware limitations
- Performance tradeoffs

Photo by Digital Reach on Unsplash
So… Was It Worth It?
❌ Not worth it if you want:
- Fast builds
- Simple pipelines
- Zero maintenance
✅ Worth it if you want:
- Full control over your pipeline
- No dependency on third-party CI providers
- Deep understanding of how everything works
- A system you can run entirely on your own machines
The Tradeoff No One Talks About
If I get this fully working, production-ready, and stable…
I technically have:
A fully self-hosted CI/CD pipeline for mobile apps
No GitHub Actions.
No CircleCI.
No per-minute billing.
Just:
- My machines
- My setup
- My electricity bill
- And… my sanity 😅
💡 Final Realization
You’re not paying with money anymore.
You’re paying with complexity.
Cloud CI/CD:
- Pay with money
- Save time and mental load
Self-hosted CI/CD:
- Save money (long-term)
- Pay with time, effort, and maintenance
My Take
Will I still use GitHub Actions?
Probably — especially when I just want things to work.
But I’m no longer dependent on it.
Because now I know:
I can run everything on my own infrastructure.
And that changes how I think about building systems.
What’s Next
I still have one idea left:
- Using a macOS VM (ARM via Apple Virtualization)
- Running builds natively without emulation
In theory, this should:
- Avoid Hermes issues
- Improve performance significantly
If that works…
This setup might actually be viable — even for production.
Final Thought
Self-hosting CI/CD for mobile isn’t just replacing a tool.
It’s taking ownership of the entire environment.
And once you take that ownership…
You also get the freedom to decide:
Do I want to pay with money — or with complexity?

Photo by engin akyurt on Unsplash

Top comments (0)