Deployment Overview
How Nebutra ships in production — Cloudflare edge, Vercel for marketing/docs, ECS for app/auth/API — plus Docker self-host options.
Deployment options
| Option | Best for | Complexity | Cost |
|---|---|---|---|
| Split (recommended for Nebutra.com) | Marketing on Vercel + app/API on a Cloud VM | Medium | Infrastructure + optional Vercel |
| Vercel (frontends only) | Docs, landing, optional web/auth cutover | Low | Hobby/Pro usage limits |
| Docker / PM2 self-hosted | Data residency, full control | Medium | Your VMs |
| Cloudflare Workers (gateway) | Edge API entry (see monorepo target config) | Medium | Workers free tier + paid overages |
Production architecture (nebutra.com today)
Public DNS sits on Cloudflare (CDN / WAF). Origins are split:
User
│
▼
Cloudflare DNS + proxy
│
├─── apps/landing nebutra.com → Vercel
├─── apps/sailor-docs nebutra.com/docs → Vercel
│
├─── apps/web app.nebutra.com → ECS (PM2 Next standalone)
├─── apps/auth auth.nebutra.com → ECS (PM2 auth-center)
├─── backends/gateway api.nebutra.com → ECS (PM2 Hono / Node)
└─── apps/idp sso.nebutra.com → ECS (OIDC issuer; keep stable)
│
├─── PostgreSQL (Supabase / Neon / RDS)
├─── Redis / KV (Upstash or Cloudflare KV)
└─── ClickHouse (metering / analytics)| Hostname | App | Steady-state host |
|---|---|---|
nebutra.com | apps/landing | Vercel |
nebutra.com/docs | apps/sailor-docs | Vercel |
app.nebutra.com | apps/web | ECS (Next standalone). Vercel project nebutra-web is optional cutover |
auth.nebutra.com | apps/auth | ECS. Vercel project nebutra-auth is optional cutover |
api.nebutra.com | backends/gateway | ECS (not Vercel Functions in production) |
sso.nebutra.com | apps/idp | ECS (permanent issuer — move carefully) |
See also monorepo ops: docs/DOMAINS.md and docs/ops/nebutra/web-auth-vercel-cutover.md.
Web build note
apps/web default pnpm build is Vite. Production ECS (and Vercel if you cut over) must use pnpm --filter @nebutra/web run build:next so .next / standalone is produced. Official workflow: .github/workflows/deploy-ecs.yml.
Service-to-service auth
Internal x-service-token is a short-lived HS256 JWT (@nebutra/auth signServiceToken / verifyServiceToken). Legacy hex-HMAC tokens are rejected. Same contract on Python and Go helpers.
Before you deploy
Run database migrations
Always run migrations before shipping a schema-dependent app version:
pnpm db:migrateValidate environment variables
Required env vars are validated at startup. Missing secrets should fail fast. At minimum for auth + app:
| Variable | Notes |
|---|---|
AUTH_PROVIDER / NEXT_PUBLIC_AUTH_PROVIDER | Production: better-auth |
BETTER_AUTH_SECRET | Same value on auth + web |
BETTER_AUTH_URL / NEXT_PUBLIC_AUTH_URL | https://auth.nebutra.com |
AUTH_COOKIE_DOMAIN | .nebutra.com |
DATABASE_URL | Shared Postgres |
SERVICE_SECRET | S2S JWT signing |
CI/CD with GitHub Actions
| Workflow | Role |
|---|---|
ci.yml | lint → typecheck → build → test on PR/push |
deploy-ecs.yml | Manual fallback: Next standalone + gateway tarball → VM PM2 |
| Vercel Git integration | Auto-deploy landing + docs (and optional web/auth projects) |
deploy-gateway.yml / deploy-origin-ecs.yml | Per-service adapters, gated by DEPLOY_TARGET_GATEWAY / DEPLOY_TARGET_PYTHON_AI; no workflow deploys to Kubernetes |
Hobby Vercel has a daily deployment quota (~100 deployments/day; canceled/skipped can still count). Each linked project may open a deployment slot per push, so:
scripts/vercel-ignore-build.shonly builds when that app’s scope changed (app dir + its workspace deps), not the whole monorepo.- ECS-primary surfaces (
web/auth/gateway) skip Vercel auto-deploy unless you setVERCEL_ALLOW_ECS_OPTIONAL=1or commit with[vercel:apps/web](etc.). - On Hobby, prefer Git-connected only for landing + docs; keep optional cutover projects disconnected or optional.
Zero-downtime
- Vercel frontends: promote after green build; rollback via previous deployment.
- ECS PM2: release directories +
currentsymlink (ecs-deploy-remote.sh); keep previous release for one-step rollback.
Related
How is this guide?
Last updated on