<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Pat Teruel</title>
    <description>The latest articles on Forem by Pat Teruel (@patterueldev).</description>
    <link>https://forem.com/patterueldev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3813256%2Fe2e5b3d1-ee66-4e9e-ae86-a6664c600df8.jpeg</url>
      <title>Forem: Pat Teruel</title>
      <link>https://forem.com/patterueldev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/patterueldev"/>
    <language>en</language>
    <item>
      <title>The Hidden Cost of Self-Hosting Mobile CI/CD (Gitea + React Native)</title>
      <dc:creator>Pat Teruel</dc:creator>
      <pubDate>Mon, 23 Mar 2026 02:08:00 +0000</pubDate>
      <link>https://forem.com/patterueldev/the-hidden-cost-of-self-hosting-mobile-cicd-gitea-react-native-37p5</link>
      <guid>https://forem.com/patterueldev/the-hidden-cost-of-self-hosting-mobile-cicd-gitea-react-native-37p5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I thought Android CI/CD would be the easy part.&lt;br&gt;&lt;br&gt;
After all, it works perfectly on GitHub Actions.  &lt;/p&gt;

&lt;p&gt;So I tried to self-host it using Gitea.  &lt;/p&gt;

&lt;p&gt;That’s where things started breaking.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;In my previous posts, I’ve been experimenting heavily with &lt;strong&gt;Lima VMs&lt;/strong&gt; to create isolated development environments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate environments per project
&lt;/li&gt;
&lt;li&gt;No dependency conflicts
&lt;/li&gt;
&lt;li&gt;Full control over provisioning
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It worked surprisingly well.&lt;/p&gt;

&lt;p&gt;I even managed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;strong&gt;self-hosted CI/CD using Gitea Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Spin up a &lt;strong&gt;macOS runner for iOS builds&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Automate &lt;code&gt;xcodebuild&lt;/code&gt; and generate IPAs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, I thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“If I can make iOS work… Android should be easy.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;I’m currently building a personal app using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React Native
&lt;/li&gt;
&lt;li&gt;Expo
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I already have another app with the same stack running on &lt;strong&gt;GitHub Actions&lt;/strong&gt; — no issues at all. Smooth builds, predictable pipelines.&lt;/p&gt;

&lt;p&gt;So the idea was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reuse the same workflow… but run it on my own infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcl0aaq3602a67p7cgkrb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcl0aaq3602a67p7cgkrb.jpg" alt="Code" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@flowforfrank?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Ferenc Almasi&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/text-An6M5zgFPj4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Attempt #1 — Linux ARM + Docker (Lima VM)
&lt;/h2&gt;

&lt;p&gt;Since I’m on an Apple Silicon Mac, I started with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu (ARM) VM via Lima
&lt;/li&gt;
&lt;li&gt;Docker-based Gitea runner
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup worked well for other projects.&lt;/p&gt;

&lt;p&gt;But for React Native?&lt;/p&gt;

&lt;p&gt;❌ It failed.&lt;/p&gt;

&lt;p&gt;The error wasn’t immediately clear, but one thing kept popping up:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hermes&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Attempt #2 — Manual Environment Setup
&lt;/h2&gt;

&lt;p&gt;I thought maybe Docker was the issue.&lt;/p&gt;

&lt;p&gt;So I went manual:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installed JDK
&lt;/li&gt;
&lt;li&gt;Installed Android SDK
&lt;/li&gt;
&lt;li&gt;Installed Node.js
&lt;/li&gt;
&lt;li&gt;Configured environment variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After hours of setup…&lt;/p&gt;

&lt;p&gt;❌ Same failure.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb22q3qoj9x9s00zv8le.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb22q3qoj9x9s00zv8le.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@silverkblack?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Vitaly Gariev&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/man-holding-head-in-frustration-at-desk-with-laptop-bu5LEzvtAKY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  💡 First Realization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Setup ≠ Compatibility&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just because you can install everything correctly…&lt;br&gt;&lt;br&gt;
doesn’t mean everything will actually work together.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Breakthrough (and the Wall)
&lt;/h2&gt;

&lt;p&gt;After digging deeper, I found the real issue:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Hermes does not support Linux ARM.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And suddenly everything made sense.&lt;/p&gt;

&lt;p&gt;Other people were hitting the same wall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/facebook/hermes/issues/995" rel="noopener noreferrer"&gt;https://github.com/facebook/hermes/issues/995&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/facebook/react-native/issues/46504" rel="noopener noreferrer"&gt;https://github.com/facebook/react-native/issues/46504&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/facebook/react-native/issues/39814" rel="noopener noreferrer"&gt;https://github.com/facebook/react-native/issues/39814&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 Second Realization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Mobile tooling is tightly coupled to platform constraints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn’t just “Node + build tools”.&lt;/p&gt;

&lt;p&gt;You’re dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native engines (Hermes)&lt;/li&gt;
&lt;li&gt;Platform-specific binaries&lt;/li&gt;
&lt;li&gt;Architecture limitations (ARM vs x86)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Attempt #3 — “Let’s Use My Homelab”
&lt;/h2&gt;

&lt;p&gt;Okay. If ARM is the problem…&lt;/p&gt;

&lt;p&gt;Let’s switch to x86.&lt;/p&gt;

&lt;p&gt;I tried running the build on my homelab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Old Intel MacBook Pro
&lt;/li&gt;
&lt;li&gt;8GB RAM
&lt;/li&gt;
&lt;li&gt;Running services like Jellyfin
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What could go wrong?&lt;/p&gt;

&lt;p&gt;💥 Everything.&lt;/p&gt;

&lt;p&gt;The server crashed due to memory exhaustion.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7ee5lwh4xowzstwptmf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7ee5lwh4xowzstwptmf.jpg" alt="Homelab server under high load" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@dennyisrael?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Denny Bú&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/black-steel-electronic-device-Jth4utoCVNo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  💡 Third Realization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Infrastructure matters more than correctness.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even if your setup is “technically correct”…&lt;/p&gt;

&lt;p&gt;If your hardware can’t handle it, it doesn’t matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attempt #4 — x86 VM via QEMU (Back to Lima)
&lt;/h2&gt;

&lt;p&gt;Back to my Mac.&lt;/p&gt;

&lt;p&gt;This time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu x86 VM
&lt;/li&gt;
&lt;li&gt;Running via QEMU emulation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally…&lt;/p&gt;

&lt;p&gt;✅ It runs.&lt;/p&gt;

&lt;p&gt;But there’s a catch.&lt;/p&gt;

&lt;p&gt;⏳ It’s &lt;strong&gt;slow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Like… &lt;strong&gt;40+ minutes per build&lt;/strong&gt; slow.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2wwofovebvbyohrjjak.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2wwofovebvbyohrjjak.jpg" alt="Terminal showing a long-running build process" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@johnmoeses?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;John Moeses Bauan&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-cat-wearing-a-harness-sleeping-on-a-computer-desk-6mQLmJtLkEM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  💡 Fourth Realization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Emulation works — but at a cost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can &lt;em&gt;force&lt;/em&gt; compatibility…&lt;/p&gt;

&lt;p&gt;But you pay for it in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance
&lt;/li&gt;
&lt;li&gt;Time
&lt;/li&gt;
&lt;li&gt;Developer experience
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;At this point, I had to stop and ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Why does this work so easily on GitHub Actions?”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧠 Insight #1 — Cloud CI Hides the Hard Parts
&lt;/h3&gt;

&lt;p&gt;When you use platforms like GitHub Actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t think about CPU architecture
&lt;/li&gt;
&lt;li&gt;You don’t manage SDK installations
&lt;/li&gt;
&lt;li&gt;You don’t deal with compatibility issues
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because they already solved it.&lt;/p&gt;

&lt;p&gt;You’re not just using CI/CD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You’re using &lt;strong&gt;pre-solved infrastructure&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧠 Insight #2 — Mobile CI/CD Is Not Platform-Agnostic
&lt;/h3&gt;

&lt;p&gt;Backend CI/CD is relatively straightforward.&lt;/p&gt;

&lt;p&gt;Mobile?&lt;/p&gt;

&lt;p&gt;Not even close.&lt;/p&gt;

&lt;p&gt;You’re tied to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OS constraints (macOS for iOS)&lt;/li&gt;
&lt;li&gt;CPU architecture (ARM vs x86)&lt;/li&gt;
&lt;li&gt;Vendor tooling (Android SDK, Hermes, etc.)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧠 Insight #3 — Self-Hosting Means Owning Everything
&lt;/h3&gt;

&lt;p&gt;When you self-host CI/CD, you’re not just replacing GitHub Actions.&lt;/p&gt;

&lt;p&gt;You’re taking ownership of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment provisioning
&lt;/li&gt;
&lt;li&gt;Toolchain compatibility
&lt;/li&gt;
&lt;li&gt;Hardware limitations
&lt;/li&gt;
&lt;li&gt;Performance tradeoffs
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbex1ou62478cvxpuiyf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbex1ou62478cvxpuiyf.jpg" alt="Abstract illustration representing hidden complexity" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@digitalreachmarketing?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Digital Reach&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/underwater-view-with-sunlight-filtering-through-water-ZwcCisqoAv4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  So… Was It Worth It?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Not worth it if you want:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fast builds
&lt;/li&gt;
&lt;li&gt;Simple pipelines
&lt;/li&gt;
&lt;li&gt;Zero maintenance
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Worth it if you want:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Full control over your pipeline
&lt;/li&gt;
&lt;li&gt;No dependency on third-party CI providers
&lt;/li&gt;
&lt;li&gt;Deep understanding of how everything works
&lt;/li&gt;
&lt;li&gt;A system you can run &lt;em&gt;entirely on your own machines&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Tradeoff No One Talks About
&lt;/h2&gt;

&lt;p&gt;If I get this fully working, production-ready, and stable…&lt;/p&gt;

&lt;p&gt;I technically have:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;strong&gt;fully self-hosted CI/CD pipeline for mobile apps&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No GitHub Actions.&lt;br&gt;&lt;br&gt;
No CircleCI.&lt;br&gt;&lt;br&gt;
No per-minute billing.&lt;/p&gt;

&lt;p&gt;Just:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My machines
&lt;/li&gt;
&lt;li&gt;My setup
&lt;/li&gt;
&lt;li&gt;My electricity bill
&lt;/li&gt;
&lt;li&gt;And… my sanity 😅&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 Final Realization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;You’re not paying with money anymore.  &lt;/p&gt;

&lt;p&gt;You’re paying with &lt;strong&gt;complexity&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cloud CI/CD:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay with money
&lt;/li&gt;
&lt;li&gt;Save time and mental load
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Self-hosted CI/CD:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save money (long-term)
&lt;/li&gt;
&lt;li&gt;Pay with time, effort, and maintenance
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Take
&lt;/h2&gt;

&lt;p&gt;Will I still use GitHub Actions?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Probably — especially when I just want things to work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But I’m no longer dependent on it.&lt;/p&gt;

&lt;p&gt;Because now I know:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I &lt;em&gt;can&lt;/em&gt; run everything on my own infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that changes how I think about building systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;I still have one idea left:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a &lt;strong&gt;macOS VM (ARM via Apple Virtualization)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Running builds natively without emulation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In theory, this should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid Hermes issues
&lt;/li&gt;
&lt;li&gt;Improve performance significantly
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that works…&lt;/p&gt;

&lt;p&gt;This setup might actually be viable — even for production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Self-hosting CI/CD for mobile isn’t just replacing a tool.  &lt;/p&gt;

&lt;p&gt;It’s taking ownership of the entire environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And once you take that ownership…&lt;/p&gt;

&lt;p&gt;You also get the freedom to decide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do I want to pay with money — or with complexity?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmtqcc28iklewjtezaoi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmtqcc28iklewjtezaoi.jpg" alt="Coffee beside a MacBook Pro on a desk" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@enginakyurt?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;engin akyurt&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/black-coffee-in-orange-ceramic-mug-beside-macbook-pro-x1KElsXNet0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Lima VM — Life Changing? Or a Passing Fad?</title>
      <dc:creator>Pat Teruel</dc:creator>
      <pubDate>Sat, 21 Mar 2026 02:36:19 +0000</pubDate>
      <link>https://forem.com/patterueldev/lima-vm-life-changing-or-a-passing-fad-7a6</link>
      <guid>https://forem.com/patterueldev/lima-vm-life-changing-or-a-passing-fad-7a6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3ls6wrqbn27czvu1o6m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3ls6wrqbn27czvu1o6m.jpg" alt="developer workspace laptop code" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@dkomow?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Daniil Komov&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/laptop-screen-displaying-code-with-a-small-plush-toy-JL1fffyIe00?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  I accidentally built a self-hosted iOS CI pipeline
&lt;/h3&gt;

&lt;p&gt;A few days ago, I discovered &lt;strong&gt;Lima VM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At first, it was just curiosity. I wanted a cleaner way to isolate my development environments without constantly fighting my local machine.&lt;/p&gt;

&lt;p&gt;I didn’t expect it to turn into this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I now have a &lt;strong&gt;self-hosted CI pipeline&lt;/strong&gt; that builds iOS apps using &lt;strong&gt;macOS VMs running inside my Mac&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  It Started With a Simple Problem
&lt;/h2&gt;

&lt;p&gt;Like most developers, I was juggling environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;development vs staging
&lt;/li&gt;
&lt;li&gt;different &lt;code&gt;.env&lt;/code&gt; setups
&lt;/li&gt;
&lt;li&gt;Docker containers stepping on each other
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything &lt;em&gt;worked&lt;/em&gt;… but it never felt clean.&lt;/p&gt;

&lt;p&gt;So I tried something different.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Project, Two Machines
&lt;/h2&gt;

&lt;p&gt;Instead of one machine handling everything, I split a single project into two &lt;strong&gt;Lima VMs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dev VM&lt;/strong&gt; → hot reload, fast iteration
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staging VM&lt;/strong&gt; → pull changes, build production images, test
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each VM had its own hostname:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lima-project-dev.local  
lima-project.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No conflicts. No weird container overlaps. No “wait, which environment am I in?”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzmcah7o9d1elhmmtdpu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzmcah7o9d1elhmmtdpu.jpg" alt="Computer code shot" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@helibertoarias?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Heliberto Arias&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/black-and-white-laptop-computer-IlqswL1pCMQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The setup wasn’t smooth.
&lt;/h3&gt;

&lt;p&gt;I had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;figure out Lima YAML configs
&lt;/li&gt;
&lt;li&gt;mount projects correctly
&lt;/li&gt;
&lt;li&gt;reconfigure git inside the VM
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It took a few retries. A lot of trial and error.&lt;/p&gt;

&lt;p&gt;But once it worked?&lt;/p&gt;

&lt;p&gt;It felt &lt;strong&gt;different&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then I Got Curious (Again)
&lt;/h2&gt;

&lt;p&gt;I’ve been running &lt;strong&gt;Gitea&lt;/strong&gt; in my homelab for months.&lt;/p&gt;

&lt;p&gt;I knew it supported Actions, similar to GitHub Actions—but I never fully committed to it because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Where do I even run the runners?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question basically killed my motivation before.&lt;/p&gt;

&lt;p&gt;Until Lima.&lt;/p&gt;




&lt;h2&gt;
  
  
  Running My Own CI Runners
&lt;/h2&gt;

&lt;p&gt;Instead of overthinking it, I spun up another VM.&lt;/p&gt;

&lt;p&gt;Installed the Gitea &lt;strong&gt;Act Runner&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Connected it to my instance.&lt;/p&gt;

&lt;p&gt;And… it worked.&lt;/p&gt;

&lt;p&gt;I was now running CI jobs for my private repositories—fully self-hosted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3io9yazinxbbeiuqo5i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3io9yazinxbbeiuqo5i.jpg" alt="Terminal running on screen" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jakewalker?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jake Walker&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/black-flat-screen-computer-monitor-MPKQiDpMyqU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That alone already felt like a win.&lt;/p&gt;

&lt;p&gt;But I wasn’t satisfied.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Goal: iOS Builds
&lt;/h2&gt;

&lt;p&gt;As an iOS developer, there’s always one limitation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You need macOS to build iOS apps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cloud CI solves this. GitHub Actions solves this.&lt;/p&gt;

&lt;p&gt;But I wanted to see:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I do this &lt;strong&gt;myself&lt;/strong&gt;?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  macOS Inside macOS (Yes, Really)
&lt;/h2&gt;

&lt;p&gt;Lima recently introduced &lt;strong&gt;experimental macOS VM support&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So I tried it.&lt;/p&gt;

&lt;p&gt;I set up a macOS VM… inside my Mac.&lt;/p&gt;

&lt;p&gt;Then I tried to turn it into a CI runner.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Part Was Painful
&lt;/h2&gt;

&lt;p&gt;Setting it up was not easy.&lt;/p&gt;

&lt;p&gt;I had to manually install and configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Xcode
&lt;/li&gt;
&lt;li&gt;Node.js
&lt;/li&gt;
&lt;li&gt;Cocoapods
&lt;/li&gt;
&lt;li&gt;React Native Expo dependencies
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things broke.&lt;/p&gt;

&lt;p&gt;A lot.&lt;/p&gt;

&lt;p&gt;At some point, I stopped “trying random fixes” and started documenting everything.&lt;/p&gt;

&lt;p&gt;Eventually, I built my own &lt;strong&gt;repeatable setup guide&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then I wiped the VM.&lt;/p&gt;

&lt;p&gt;Recreated it from scratch.&lt;/p&gt;

&lt;p&gt;Followed my own steps.&lt;/p&gt;

&lt;p&gt;And finally…&lt;/p&gt;




&lt;h2&gt;
  
  
  It Worked
&lt;/h2&gt;

&lt;p&gt;I triggered a Gitea Action.&lt;/p&gt;

&lt;p&gt;The runner picked it up.&lt;/p&gt;

&lt;p&gt;The macOS VM executed it.&lt;/p&gt;

&lt;p&gt;And I got:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An iOS build artifact generated using &lt;code&gt;xcodebuild&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From my own self-hosted pipeline.&lt;/p&gt;

&lt;p&gt;No GitHub Actions. No external CI.&lt;/p&gt;

&lt;p&gt;Just:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gitea
&lt;/li&gt;
&lt;li&gt;Lima VM
&lt;/li&gt;
&lt;li&gt;My own machines
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That moment honestly felt incredible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdr9v7wztv5ua39h9cs9a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdr9v7wztv5ua39h9cs9a.jpg" alt="Laptop on desk in the middle of the night" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@baltasarhenderson?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Baltasar Henderson&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-laptop-computer-sitting-on-top-of-a-desk-Z9EqrbfPIAc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Have Now
&lt;/h2&gt;

&lt;p&gt;Right now, my setup looks something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple Lima VMs for dev/staging
&lt;/li&gt;
&lt;li&gt;Ubuntu runners for general CI
&lt;/li&gt;
&lt;li&gt;macOS VM runner for iOS builds
&lt;/li&gt;
&lt;li&gt;Gitea Actions orchestrating everything
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build iOS apps automatically
&lt;/li&gt;
&lt;li&gt;Generate unsigned IPAs
&lt;/li&gt;
&lt;li&gt;Deploy them to my own distribution system (work in progress)
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Small Limitations (For Now)
&lt;/h2&gt;

&lt;p&gt;It’s not perfect.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gitea Actions currently supports &lt;code&gt;upload-artifact&lt;/code&gt; up to v3
&lt;/li&gt;
&lt;li&gt;Newer versions (v6) aren’t fully supported yet
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But honestly?&lt;/p&gt;

&lt;p&gt;That’s a small tradeoff.&lt;/p&gt;

&lt;p&gt;If needed, I can just push artifacts to another server.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned: Provisioning Lima &amp;amp; Creating Templates
&lt;/h2&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;And that changed everything.&lt;/p&gt;

&lt;p&gt;Instead of treating each VM as a one-off setup, I can now think in terms of &lt;strong&gt;templates&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From here on out, I can create custom Lima templates for my own workflows, such as:&lt;/p&gt;

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

&lt;p&gt;This turns Lima into more than just a VM tool—it becomes a &lt;strong&gt;foundation for repeatable, disposable infrastructure&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;And for me, that’s probably one of the biggest wins from this entire experiment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I’m Doing This
&lt;/h2&gt;

&lt;p&gt;Partly?&lt;/p&gt;

&lt;p&gt;Because it’s fun.&lt;/p&gt;

&lt;p&gt;But also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I want to understand how CI/CD actually works under the hood
&lt;/li&gt;
&lt;li&gt;I want control over my infrastructure
&lt;/li&gt;
&lt;li&gt;I want to build systems—not just use them
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t about replacing GitHub Actions.&lt;/p&gt;

&lt;p&gt;It’s about &lt;strong&gt;learning by building the system yourself&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is Lima VM “Life Changing”?
&lt;/h2&gt;

&lt;p&gt;Too early to say.&lt;/p&gt;

&lt;p&gt;But right now?&lt;/p&gt;

&lt;p&gt;It already changed how I think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;development environments
&lt;/li&gt;
&lt;li&gt;isolation
&lt;/li&gt;
&lt;li&gt;automation
&lt;/li&gt;
&lt;li&gt;self-hosted infrastructure
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if I stop using it someday…&lt;/p&gt;

&lt;p&gt;This experiment was already worth it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Explore &lt;strong&gt;ephemeral runners&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Improve VM provisioning (less manual setup)
&lt;/li&gt;
&lt;li&gt;Integrate into a real product workflow
&lt;/li&gt;
&lt;li&gt;Write a step-by-step guide for macOS runners
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://lima-vm.io/" rel="noopener noreferrer"&gt;https://lima-vm.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lima-vm.io/docs/usage/guests/macos/" rel="noopener noreferrer"&gt;https://lima-vm.io/docs/usage/guests/macos/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://about.gitea.com/" rel="noopener noreferrer"&gt;https://about.gitea.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.gitea.com/usage/actions/act-runner" rel="noopener noreferrer"&gt;https://docs.gitea.com/usage/actions/act-runner&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Lima VM &amp; faasd: A Beginner’s Experiment With Isolated Development Environments</title>
      <dc:creator>Pat Teruel</dc:creator>
      <pubDate>Mon, 16 Mar 2026 03:36:15 +0000</pubDate>
      <link>https://forem.com/patterueldev/lima-vm-faasd-a-beginners-experiment-with-isolated-development-environments-33ba</link>
      <guid>https://forem.com/patterueldev/lima-vm-faasd-a-beginners-experiment-with-isolated-development-environments-33ba</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidqyqobwdkk2ye4utkac.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidqyqobwdkk2ye4utkac.jpg" alt="Developer Computer" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@theconnectednarrative?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;The Connected Narrative&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-person-working-on-a-laptop-aEv8ednzJ2E?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently I started experimenting with &lt;strong&gt;Lima&lt;/strong&gt; while rethinking how I manage development environments and small backend services.&lt;/p&gt;

&lt;p&gt;What began as simple curiosity quickly evolved into a practical approach: using &lt;strong&gt;Lima VMs as disposable development environments&lt;/strong&gt; alongside running &lt;strong&gt;faasd in my homelab for serverless experiments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm still in the early stages of this setup, but I wanted to document the journey and the reasoning behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Started Exploring Lima
&lt;/h2&gt;

&lt;p&gt;Like many developers, my laptop gradually accumulated development tools over time.&lt;/p&gt;

&lt;p&gt;Different languages, frameworks, and dependencies.&lt;/p&gt;

&lt;p&gt;Most of the time, this works fine, but occasionally you run into issues like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependency conflicts&lt;/li&gt;
&lt;li&gt;toolchain mismatches&lt;/li&gt;
&lt;li&gt;leftover configuration from old projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, you can manage all of this carefully on one machine.&lt;/p&gt;

&lt;p&gt;But I started wondering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if every project had its own isolated environment?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That curiosity led me to &lt;strong&gt;Lima&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For those unfamiliar, &lt;strong&gt;Lima&lt;/strong&gt; is a tool that runs lightweight Linux virtual machines on macOS, allowing developers to work with real Linux environments without needing a full desktop VM.&lt;/p&gt;

&lt;p&gt;It’s somewhat similar in spirit to WSL on Windows but designed specifically for macOS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Bother with Isolation?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kb48jfv11ldh2aapaam.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kb48jfv11ldh2aapaam.gif" alt="But Why" width="498" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At some point, you might ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why complicate things?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You could absolutely just install everything directly on your machine and manage it carefully.&lt;/p&gt;

&lt;p&gt;But isolating environments changes the mindset.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One machine
Many tools
Many projects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get something closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project A → VM A
Project B → VM B
Experimental stack → disposable VM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something breaks, you simply destroy the VM and recreate it.&lt;/p&gt;

&lt;p&gt;No leftover dependencies.&lt;/p&gt;

&lt;p&gt;No mysterious configuration conflicts.&lt;/p&gt;

&lt;p&gt;It also encourages cleaner setups because every environment starts fresh.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Development Setup
&lt;/h2&gt;

&lt;p&gt;Right now my setup looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MacBook (macOS)
   └─ Lima VM
        └─ Development tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kl7smgtdodfh471jo09.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kl7smgtdodfh471jo09.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jexo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jexo&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/person-using-macbook-pro-on-pink-and-white-floral-textile-73REk-BB7-Y?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside Lima, I install the tools required for a specific project.&lt;/p&gt;

&lt;p&gt;If the environment becomes messy or outdated, I can simply destroy the VM and recreate it.&lt;/p&gt;

&lt;p&gt;This approach also lets me simulate something closer to a real Linux server environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Homelab Side Project: faasd
&lt;/h2&gt;

&lt;p&gt;Outside of development, I run a small &lt;strong&gt;homelab&lt;/strong&gt; where I host services for personal projects.&lt;/p&gt;

&lt;p&gt;Whenever I build small applications, they usually require some kind of backend service.&lt;/p&gt;

&lt;p&gt;Traditionally that meant adding more containers to my homelab infrastructure.&lt;/p&gt;

&lt;p&gt;But I’ve always been fascinated with &lt;strong&gt;serverless platforms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Services like AWS Lambda or Firebase Functions make it easy to deploy small pieces of code without managing full servers.&lt;/p&gt;

&lt;p&gt;The problem is that I wanted something &lt;strong&gt;self-hosted&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s when I discovered &lt;strong&gt;OpenFaaS&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Discovering faasd
&lt;/h2&gt;

&lt;p&gt;OpenFaaS is a powerful serverless framework, but setting it up can be fairly complex.&lt;/p&gt;

&lt;p&gt;While exploring the ecosystem I discovered &lt;strong&gt;faasd&lt;/strong&gt;, a lightweight single-node version designed for simpler deployments.&lt;/p&gt;

&lt;p&gt;Perfect for experimentation.&lt;/p&gt;

&lt;p&gt;Or so I thought.&lt;/p&gt;




&lt;h2&gt;
  
  
  My First Wrong Assumption
&lt;/h2&gt;

&lt;p&gt;Because I was already familiar with &lt;strong&gt;Docker&lt;/strong&gt;, I initially assumed faasd would integrate easily with my existing Docker setup.&lt;/p&gt;

&lt;p&gt;That assumption turned out to be wrong.&lt;/p&gt;

&lt;p&gt;faasd runs on &lt;strong&gt;containerd&lt;/strong&gt;, not Docker, and this caused conflicts with my existing environment.&lt;/p&gt;

&lt;p&gt;At this point I considered several options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spinning up a cloud server just for experimentation&lt;/li&gt;
&lt;li&gt;abandoning the idea and using AWS Lambda&lt;/li&gt;
&lt;li&gt;finding a way to isolate the environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s where Lima became useful again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Separating Development and Runtime
&lt;/h2&gt;

&lt;p&gt;Eventually I landed on a setup that felt much cleaner.&lt;/p&gt;

&lt;p&gt;My &lt;strong&gt;development environment&lt;/strong&gt; runs in Lima on my MacBook.&lt;/p&gt;

&lt;p&gt;My &lt;strong&gt;faasd environment&lt;/strong&gt; runs on my homelab Linux machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MacBook (macOS)
   └─ Lima VM
        └─ Development environment

Homelab Server (Linux)
   └─ faasd
        └─ serverless functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yv7utbb1nx51jcp73s6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yv7utbb1nx51jcp73s6.jpg" alt=" " width="800" height="571"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@albertstoynov?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Albert Stoynov&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/yellow-and-green-cables-are-neatly-connected-yhJVLxcquEY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This separation allows me to experiment with serverless functions without polluting my main development system.&lt;/p&gt;


&lt;h2&gt;
  
  
  Making faasd Accessible Remotely
&lt;/h2&gt;

&lt;p&gt;Once faasd was running in my homelab, I wanted to take things a step further.&lt;/p&gt;

&lt;p&gt;I exposed the faasd gateway using &lt;strong&gt;Cloudflare Tunnels&lt;/strong&gt;, which allowed me to access it remotely without opening ports on my home network.&lt;/p&gt;

&lt;p&gt;The flow now looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   ↓
Cloudflare Tunnel
   ↓
faasd Gateway
   ↓
Serverless Function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it possible to deploy and test functions remotely from my development environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where I Am Now
&lt;/h2&gt;

&lt;p&gt;Right now I’m still very much at the &lt;strong&gt;beginner stage&lt;/strong&gt; of this setup.&lt;/p&gt;

&lt;p&gt;But I now have a working environment where I can experiment with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lima-based development environments&lt;/li&gt;
&lt;li&gt;self-hosted serverless functions&lt;/li&gt;
&lt;li&gt;isolated project setups&lt;/li&gt;
&lt;li&gt;remote function deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And most importantly, I can do all of this &lt;strong&gt;without affecting my main development machine or homelab infrastructure&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Experiment Matters
&lt;/h2&gt;

&lt;p&gt;For developers who enjoy experimenting with infrastructure, Lima opens an interesting possibility.&lt;/p&gt;

&lt;p&gt;Instead of treating your laptop as one large development environment, you can treat it more like a &lt;strong&gt;mini cloud&lt;/strong&gt;, where each project runs in its own isolated space.&lt;/p&gt;

&lt;p&gt;It’s still an evolving workflow for me, but the idea of &lt;strong&gt;disposable development environments&lt;/strong&gt; combined with &lt;strong&gt;self-hosted serverless platforms&lt;/strong&gt; feels very powerful.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Want to Explore Next
&lt;/h2&gt;

&lt;p&gt;Some things I want to experiment with next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;running multiple Lima VMs for different projects&lt;/li&gt;
&lt;li&gt;integrating faasd with real applications&lt;/li&gt;
&lt;li&gt;building small APIs as serverless functions&lt;/li&gt;
&lt;li&gt;improving deployment workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is still very much an ongoing experiment, but that's part of the fun.&lt;/p&gt;

&lt;p&gt;If you're experimenting with &lt;strong&gt;Lima&lt;/strong&gt;, &lt;strong&gt;homelabs&lt;/strong&gt;, or &lt;strong&gt;self-hosted serverless platforms&lt;/strong&gt;, I'd be curious to hear how you're using them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;Looking ahead, here’s what I plan to focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automating Lima VM provisioning and configuration for faster setup&lt;/li&gt;
&lt;li&gt;Creating reusable faasd function templates for common use cases&lt;/li&gt;
&lt;li&gt;Exploring CI/CD pipelines that integrate with my Lima and faasd environments&lt;/li&gt;
&lt;li&gt;Investigating security best practices for exposing serverless functions remotely&lt;/li&gt;
&lt;li&gt;Documenting lessons learned and sharing guides for others interested in similar setups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This roadmap will evolve as I learn more and refine the workflow, but it provides a clear direction for the next steps.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lima-vm/lima" rel="noopener noreferrer"&gt;Lima (Official)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lima-vm.io/" rel="noopener noreferrer"&gt;Lima Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openfaas/faasd" rel="noopener noreferrer"&gt;faasd (Official)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openfaas.com/faasd/" rel="noopener noreferrer"&gt;faasd Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>I've Spent 10 Years in Mobile Development. What DON'T I Know?</title>
      <dc:creator>Pat Teruel</dc:creator>
      <pubDate>Sun, 08 Mar 2026 17:42:53 +0000</pubDate>
      <link>https://forem.com/patterueldev/ive-spent-10-years-in-mobile-development-what-dont-i-know-22ih</link>
      <guid>https://forem.com/patterueldev/ive-spent-10-years-in-mobile-development-what-dont-i-know-22ih</guid>
      <description>&lt;p&gt;For the past decade, I’ve worked primarily as a mobile developer, focusing on iOS and mobile platforms. That has been my professional identity for most of my career, and it’s something I’m genuinely passionate about.&lt;/p&gt;

&lt;p&gt;But recently, I started asking myself a difficult question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After 10 years in mobile development, what &lt;em&gt;don’t&lt;/em&gt; I know?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxw76zqhpnkvi4rnjhbci.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxw76zqhpnkvi4rnjhbci.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@douglasamarelo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Douglas Lopes&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-computer-desk-with-two-monitors-and-a-mouse-OQT9s7fHeO0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Mobile Developer With Curiosity
&lt;/h3&gt;

&lt;p&gt;Even though I’ve always identified professionally as a mobile developer, my curiosity has never been limited to mobile.&lt;/p&gt;

&lt;p&gt;Over the years, I’ve explored different parts of the tech stack through personal projects and experiments. I've built small backend services using Java and Kotlin with Spring Boot, experimented with NodeJS, worked with Flutter and Firebase on a side project with a friend, and learned how to deploy services using Docker and AWS.&lt;/p&gt;

&lt;p&gt;Outside of work, I’ve also built my own small homelab to host services for personal use. These projects weren’t part of my main job, but they helped me understand how different parts of a system work together.&lt;/p&gt;

&lt;p&gt;Despite all of that exploration, my day-to-day professional identity remained the same:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mobile Developer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And I was comfortable with that.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Your Role Changes
&lt;/h3&gt;

&lt;p&gt;At one point, I recommended a project internally and eventually found myself overseeing it from a project management perspective.&lt;/p&gt;

&lt;p&gt;I learned a lot about planning, coordination, and the processes required to bring a product to production. But I also realized something important about myself.&lt;/p&gt;

&lt;p&gt;My brain isn’t wired for project management.&lt;/p&gt;

&lt;p&gt;What excites me most is still the engineering work itself: designing systems, writing code, building infrastructure, and figuring out how different parts of a product fit together.&lt;/p&gt;

&lt;p&gt;So even while overseeing the project, I naturally gravitated back toward engineering tasks — setting up CI/CD pipelines with GitHub Actions, managing parts of the AWS infrastructure, and helping with the technical architecture.&lt;/p&gt;

&lt;p&gt;That experience reinforced something I already suspected:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I enjoy building systems.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Realization
&lt;/h3&gt;

&lt;p&gt;As I interacted with engineers working in different stacks — backend engineers, infrastructure specialists, and full-stack developers — something slowly became clear to me.&lt;/p&gt;

&lt;p&gt;Even with ten years of experience, I was still an amateur in the broader technology landscape.&lt;/p&gt;

&lt;p&gt;And that’s not necessarily a bad thing.&lt;/p&gt;

&lt;p&gt;Technology is far too large for any one person to fully master. Every engineer specializes somewhere. But realizing the size of that landscape made me rethink the direction of my own growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rethinking My Path
&lt;/h3&gt;

&lt;p&gt;Instead of staying within a single specialization, I want to expand my perspective as an engineer.&lt;/p&gt;

&lt;p&gt;Not by abandoning mobile development — far from it. Mobile development will always be a major part of what I do.&lt;/p&gt;

&lt;p&gt;But I want to better understand the systems behind the applications we build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend architecture&lt;/li&gt;
&lt;li&gt;Infrastructure and deployment&lt;/li&gt;
&lt;li&gt;Data modeling&lt;/li&gt;
&lt;li&gt;CI/CD and operational systems&lt;/li&gt;
&lt;li&gt;End-to-end product development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, I want to grow into what I think of as a &lt;strong&gt;Product Engineer&lt;/strong&gt; — someone who can understand and contribute to a product from idea to deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  In the Era of AI
&lt;/h3&gt;

&lt;p&gt;We’re entering a period where AI tools are becoming a normal part of software development.&lt;/p&gt;

&lt;p&gt;Some developers respond to this with fear — worrying that automation might replace parts of our jobs.&lt;/p&gt;

&lt;p&gt;Personally, I see it differently.&lt;/p&gt;

&lt;p&gt;If anything, this era makes it more important to &lt;strong&gt;broaden our understanding of systems&lt;/strong&gt;. AI can help generate code, but building reliable products still requires engineers who understand architecture, trade-offs, and how different components interact.&lt;/p&gt;

&lt;p&gt;For me, that means continuing to learn, experiment, and expand beyond my original specialization.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Next Step
&lt;/h3&gt;

&lt;p&gt;So I’ve decided to take a step back and map out the gaps in my own knowledge.&lt;/p&gt;

&lt;p&gt;Not as a criticism of where I am today, but as a roadmap for where I want to go next.&lt;/p&gt;

&lt;p&gt;My goal is to gradually build deeper experience across the full lifecycle of a product — from writing code to designing systems and running them in production.&lt;/p&gt;

&lt;p&gt;The first step is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build something end-to-end.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A real application, with real infrastructure behind it.&lt;/p&gt;

&lt;p&gt;And document the journey along the way.&lt;/p&gt;




&lt;p&gt;Mobile development isn’t going anywhere in my career. It will always be one of the areas I care about most.&lt;/p&gt;

&lt;p&gt;But moving forward, I want to challenge myself to build not just apps — but the entire systems behind them.&lt;/p&gt;

</description>
      <category>career</category>
      <category>ios</category>
      <category>learning</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
