Documentation

Services

What you'll have at the end: one or more long-running processes, such as an API, a collector and a queue worker, running on Vura from their start commands, each on its own machine.

Services are rolling out team by team. If saving services says they are not enabled, ask us to turn them on. A deploy from a team without access fails with "Services are not enabled for this team yet." Services also need an active paid plan on your team; a deploy without one fails with "Hot server placement requires an active paid plan."

Declare services

In vura.json at your project root:

{
  "node": 24,
  "build": "pnpm run build",
  "services": {
    "api":    { "type": "web", "start": "node dist/api.mjs", "health": "/health" },
    "worker": { "type": "worker", "start": "node dist/worker.mjs", "size": "small" }
  }
}

Or add them in the dashboard under Settings → Services. When vura.json has services, it wins field by field. The dashboard marks fields it sets as "Set in vura.json", and dashboard services the file leaves out as "not in vura.json".

Field Meaning
type web gets an HTTPS host; worker has no public port at all
start the command, run with /bin/sh -c in the service directory. It must stay in the foreground (no &, nohup, pm2 start)
root directory to run in, relative to the repo (default: the project root)
health web: a path such as "/health" that must answer 2xx within 2 s (default: the port accepts connections). worker: { "port": 4711, "path": "/health" } (default: the process is alive)
size nano 256 MB · small 512 MB (default) · medium 1 GB · large 2 GB / 2 vCPU. Pro allows up to 1 GB / 2 vCPU per machine, so medium is the largest size Pro plans currently reach
concurrency web only: connections one machine takes at once (default 250, max 2000)

Services need an active paid plan, so a free plan cannot run them at any size. Leave size off and it clamps down to the largest size your plan allows on its own. A plan with a small cap shrinks that default to fit: on starter, which caps service size at 256 MB, a service with no size set runs as nano with nothing to change. Set a size yourself and it stays fixed: if it is still above your plan's cap, the deploy fails with 422 SERVICE_SIZE_NOT_ALLOWED.

Service names start with a lowercase letter and use only lowercase letters, digits and -, up to 20 characters. They cannot contain --, start with d-, or end with -. A project has at most 10 services.

Ports and hosts

Your app must listen on process.env.PORT (3001) and host process.env.HOST (loopback, 127.0.0.1). Vura's supervisor is the only thing listening publicly on the machine, and it forwards only signed requests from the Vura edge. Binds to 0.0.0.0 or :: are pinned back to that same loopback host.

Env vars per service

On Settings → Environment Variables, choose All services or one service. A service gets the all-services values, overridden by its own. The build only sees all-services values. Names starting with FLY_, R2_, CLOUDFLARE_, EDGE_, HOT_ORIGIN_, INTERNAL_EDGE_, VURA_ORIGIN_AUTH_, VURA_RUNTIME_ or VURA_SERVICE_ are reserved at runtime. If you need one during the build, save it for All services with target "Build" instead.

Client IP

Read the caller's address from x-vura-client-ip. The Vura edge always overwrites it from Cloudflare's verified connecting IP before your request reaches your service, so it is the one header you can trust. x-forwarded-for, x-real-ip and fly-client-ip are also rewritten to the same address for compatibility with generic middleware, but x-vura-client-ip is the canonical, documented one to read.

Deploys, promotion and rollback

Logs

Runtime logs show [service] on each line. Filter by service on the deployment page.