Deploying Grit apps

This page is optional reading

Orbita is a general-purpose PaaS and needs no framework. This page is for people using the Grit framework — because we own Grit too, Orbita recognises those apps and gives them a zero-config fast path. It's the same idea as Nixpacks being a fast path for Rails: a recognised app type, not a requirement.

Why Grit apps are special

A Grit app has a known shape, declared in grit.json at the repo root. Orbita reads it and derives everything else: how many services, what to build, from which context, on which port, which database, and when to migrate. You write no Dockerfile and no build config.

Everything below is derived — you never type it:

From grit.jsonOrbita derives
architecture: single1 container — one Go binary with the SPA embedded, on :8080
architecture: api1 container — the Go API on :8080
architecture: double2 containers — api + web
architecture: triple3 containers — api + web + admin (+ docs if present)

mobile is rejected; expo and desktop are never deployed.

Orbita reuses the Dockerfiles Grit already ships

It does not generate a Dockerfile and does not fall back to Nixpacks for Grit apps. Grit ships correct, multi-stage Dockerfiles; Orbita builds those with the right contexts (the API from apps/api, Next.js apps from the repo root with NEXT_PUBLIC_API_URL baked from your API domain).

The manifest

You write this once. See the full spec.

orbita.yaml
yaml
app: rental
repo: MUKE-coder/rental
branch: main
addons: [postgres, redis]
domains:
  web:   rental.example.com
  admin: admin.rental.example.com
  api:   api.rental.example.com
migrate: true
env:
  from: .env.production   # encrypted into Orbita, never committed

Deploy it

First, make sure the CLI knows your server. If you ran orbita init, it's already registered. Otherwise connect to it once:

Local terminal (your PC)
bash
orbita login https://orbita.example.com     # once — registers the host as "prod"

Then, from the project directory (the one with grit.json):

Local terminal (your PC)
bash
orbita github-auth          # once — store a GitHub token (repo + admin:repo_hook)
orbita deploy --host prod

No orbita.yaml yet? A first-run wizard generates one from the detected app shape.

Preview without changing anything:

Local terminal (your PC)
bash
orbita deploy --plan --host prod
Output
▸ Plan (dry run — nothing will be changed)
  App:       rental
  Mode:      triple
  Migrate:   true
  Addons:    postgres, redis
 
  create  rental-api    → api.rental.example.com
  create  rental-web    → rental.example.com
  create  rental-admin  → admin.rental.example.com

What happens, in order

  1. Detectgrit.json at the repo root marks it a Grit app; architecture picks the strategy.
  2. Resolve the host — API URL + orb_ token from ~/.orbita/hosts.yaml.
  3. Ensure the repo — create it private if missing, then push.
  4. Reconcile — org, project, environment, addons, env + secrets, domains. Idempotent.
  5. Build — each service from the Dockerfiles Grit ships.
  6. Migratecmd/migrate in a one-off container, under a Postgres advisory lock.
  7. Cut over — only if the migration succeeded. Previous images are kept for rollback.

Migrations gate the cutover

A failed migration aborts the deploy

Orbita runs migrations before cutover, under an advisory lock so two concurrent deploys can't race. Non-zero exit = deploy stops and the previous version keeps serving. You never cut over to a schema-mismatched image.

The most common failure: go.sum isn't committed, so go run ./cmd/migrate can't resolve modules. Commit it — real Grit apps ship it.

Local terminal (your PC)
bash
orbita logs --host prod --service migrate

Batteries included

Mounted on the API by default:

  • Pulse — latency, SQL, errors → https://api.rental.example.com/pulse/ui
  • Sentinel — WAF, rate limiting, anomalies → https://api.rental.example.com/sentinel/ui
  • GORM Studio — off by default; it edits live data. Enable with studio: true.

Not using Grit?

Everything still works — Orbita just takes a different path. See deploying your first app for the Docker image, Compose, Dockerfile, and Nixpacks routes, and the orbita.yaml spec for how the build path is chosen.