Venelx Docs

Self-Hosting Overview

Venelx is a split system: the dashboard always runs on Vercel, while you choose where the API (control plane) and the build workers run. This page helps you pick a layout; the sub-pages cover each piece in depth.

The tiers

TierHostPackageRuns
FrontendVercelvenelx-frontendNext.js dashboard — calls the API only
Control planeCloud Run / EC2 / GCE VM, or a Mac behind a tunnelvenelx-backendExpress, Prisma, queue enqueue, auth, B2 presign, log SSE
Build workersOne or more Mac / Linux / Windows machinesvenelx-workerBullMQ consumer, pipeline, Xcode / EAS / Android builds
Mobile appApp storesvenelx-appExpo companion app — calls the API only
QueueUpstash (or any managed Redis)BullMQ; API enqueues, workers consume
DatabaseMongoDB AtlasProjects, jobs, users, billing
ArtifactsBackblaze B2Metadata + presign on the API; workers upload bytes
text
  Users ──► Vercel (dashboard)
                │ HTTPS
                ▼
            API (control plane) ──► MongoDB Atlas · B2
                │ enqueue
                ▼
            Redis (Upstash)
                │ consume (outbound only)
        ┌───────┴────────┐
        ▼                ▼
   Worker: mac-ios   Worker: linux-android

Two supported layouts

A — Mac mini monorepoB — Cloud control plane + workers
APIMac (:4000, behind Cloudflare Tunnel)Cloud Run / GCE / EC2
WorkerSame Mac, second processOne or more Mac / Linux machines
RedisUpstash or local redis://127.0.0.1Upstash (reachable from API + workers)
FrontendVercelVercel
Good forSingle-machine setups, home labProduction fleets, scaling workers

Use Upstash in both layouts so migrating A → B is only a matter of moving the API and changing API_URL on workers — not re-topologizing Redis.

Production rules

These are enforced at startup via VENELX_DEPLOY_ROLE (api or worker) in both packages:

RuleMeaning
Enqueue only on APIRUN_QUEUE_WORKER=false on the backend in production
Consume on workersRUN_QUEUE_WORKER=true and WORKER_AGENT_ONLY=true on every build host
Separate processesAPI and worker may share one Mac only as two processes — never one server
B2 keys on API onlyWorkers upload through presigned URLs (B2_UPLOAD_VIA_API=true)

Invalid in production: RUN_QUEUE_WORKER=true on the API, WORKER_AGENT_ONLY=true on the main backend, or builds running inside the Express process. The API health endpoint reports queueConsumerOnApi — it must be false.

Deployment checklist (summary)

  1. Upstash REDIS_URL on the API and every worker (identical string).
  2. Deploy the API with RUN_QUEUE_WORKER=false; verify queueConsumerOnApi: false at /api/health.
  3. Deploy the frontend on Vercel with NEXT_PUBLIC_API_URL / NEXT_PUBLIC_WS_URL.
  4. Install worker(s) on each build machine and confirm they show online in the dashboard.
  5. End-to-end: enqueue a build → watch SSE logs → download a b2: artifact.

In this section

Why Mac workers for iOS

EAS local iOS builds (eas build --local) require macOS + Xcode — cloud Linux VMs cannot produce an .ipa. Android builds run fine on Linux/WSL2 workers, so a common fleet is one Mac for ios plus one Linux box for android-preview,android-production.