DEV Community

Pat Teruel
Pat Teruel

Posted on

The Hidden Cost of Self-Hosting Mobile CI/CD (Gitea + React Native)

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 xcodebuild and 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.


Code
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:


💡 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.


Homelab server under high load
Photo by Denny Bú on Unsplash


💡 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.


Terminal showing a long-running build process
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

Abstract illustration representing hidden complexity
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?


Coffee beside a MacBook Pro on a desk
Photo by engin akyurt on Unsplash


Top comments (0)