DEV Community

Pat Teruel
Pat Teruel

Posted on

Lima VM — Life Changing? Or a Passing Fad?

developer workspace laptop code

Photo by Daniil Komov on Unsplash

I accidentally built a self-hosted iOS CI pipeline

A few days ago, I discovered Lima VM.

At first, it was just curiosity. I wanted a cleaner way to isolate my development environments without constantly fighting my local machine.

I didn’t expect it to turn into this:

I now have a self-hosted CI pipeline that builds iOS apps using macOS VMs running inside my Mac.


It Started With a Simple Problem

Like most developers, I was juggling environments:

  • development vs staging
  • different .env setups
  • Docker containers stepping on each other

Everything worked… but it never felt clean.

So I tried something different.


One Project, Two Machines

Instead of one machine handling everything, I split a single project into two Lima VMs:

  • Dev VM → hot reload, fast iteration
  • Staging VM → pull changes, build production images, test

Each VM had its own hostname:

lima-project-dev.local  
lima-project.local
Enter fullscreen mode Exit fullscreen mode

No conflicts. No weird container overlaps. No “wait, which environment am I in?”

Computer code shot

Photo by Heliberto Arias on Unsplash

The setup wasn’t smooth.

I had to:

  • figure out Lima YAML configs
  • mount projects correctly
  • reconfigure git inside the VM

It took a few retries. A lot of trial and error.

But once it worked?

It felt different.


Then I Got Curious (Again)

I’ve been running Gitea in my homelab for months.

I knew it supported Actions, similar to GitHub Actions—but I never fully committed to it because:

“Where do I even run the runners?”

That question basically killed my motivation before.

Until Lima.


Running My Own CI Runners

Instead of overthinking it, I spun up another VM.

Installed the Gitea Act Runner.

Connected it to my instance.

And… it worked.

I was now running CI jobs for my private repositories—fully self-hosted.

Terminal running on screen

Photo by Jake Walker on Unsplash

That alone already felt like a win.

But I wasn’t satisfied.


The Real Goal: iOS Builds

As an iOS developer, there’s always one limitation:

You need macOS to build iOS apps.

Cloud CI solves this. GitHub Actions solves this.

But I wanted to see:

Can I do this myself?


macOS Inside macOS (Yes, Really)

Lima recently introduced experimental macOS VM support.

So I tried it.

I set up a macOS VM… inside my Mac.

Then I tried to turn it into a CI runner.


This Part Was Painful

Setting it up was not easy.

I had to manually install and configure:

  • Xcode
  • Node.js
  • Cocoapods
  • React Native Expo dependencies

Things broke.

A lot.

At some point, I stopped “trying random fixes” and started documenting everything.

Eventually, I built my own repeatable setup guide.

Then I wiped the VM.

Recreated it from scratch.

Followed my own steps.

And finally…


It Worked

I triggered a Gitea Action.

The runner picked it up.

The macOS VM executed it.

And I got:

An iOS build artifact generated using xcodebuild.

From my own self-hosted pipeline.

No GitHub Actions. No external CI.

Just:

  • Gitea
  • Lima VM
  • My own machines

That moment honestly felt incredible.

Laptop on desk in the middle of the night
Photo by Baltasar Henderson on Unsplash


What I Have Now

Right now, my setup looks something like this:

  • Multiple Lima VMs for dev/staging
  • Ubuntu runners for general CI
  • macOS VM runner for iOS builds
  • Gitea Actions orchestrating everything

I can now:

  • Build iOS apps automatically
  • Generate unsigned IPAs
  • Deploy them to my own distribution system (work in progress)

Small Limitations (For Now)

It’s not perfect.

For example:

  • Gitea Actions currently supports upload-artifact up to v3
  • Newer versions (v6) aren’t fully supported yet

But honestly?

That’s a small tradeoff.

If needed, I can just push artifacts to another server.


What I Learned: Provisioning Lima & Creating Templates

One of the most valuable things I gained from this experience wasn’t just getting everything to work—it was learning how to provision Lima VMs properly and create reusable templates.

Setting up a macOS VM from scratch was not easy. It involved a lot of trial and error, debugging, and repeated deployments. But that process forced me to understand how Lima’s configuration works at a deeper level, especially its YAML-based provisioning system.

And that changed everything.

Instead of treating each VM as a one-off setup, I can now think in terms of templates.

From here on out, I can create custom Lima templates for my own workflows, such as:

  • Spinning up a fresh VM for new project development
  • Creating pre-configured Ubuntu runners for Gitea Actions
  • Preparing environments with Docker and commonly used services already set up
  • Bootstrapping CI/CD tools without installing anything directly on my host machine

This turns Lima into more than just a VM tool—it becomes a foundation for repeatable, disposable infrastructure.

The initial setup may be painful, but once you’ve built your own provisioning templates, every new environment becomes significantly faster and more consistent.

And for me, that’s probably one of the biggest wins from this entire experiment.


Why I’m Doing This

Partly?

Because it’s fun.

But also:

  • I want to understand how CI/CD actually works under the hood
  • I want control over my infrastructure
  • I want to build systems—not just use them

This isn’t about replacing GitHub Actions.

It’s about learning by building the system yourself.


Is Lima VM “Life Changing”?

Too early to say.

But right now?

It already changed how I think about:

  • development environments
  • isolation
  • automation
  • self-hosted infrastructure

Even if I stop using it someday…

This experiment was already worth it.


What’s Next

  • Explore ephemeral runners
  • Improve VM provisioning (less manual setup)
  • Integrate into a real product workflow
  • Write a step-by-step guide for macOS runners

References

Top comments (0)