garage-erp/DEPLOY_COOLIFY.md

3.9 KiB

Garage dashboard (garage-erp) — Coolify deploy

Domain: tenant.reparee.com Build: Docker (multi-stage), Next.js standalone output Port: 3000 inside container; Coolify maps to 80/443 + TLS


1. New Application in Coolify

  1. + New Resource → Application → Public Repository (or GitHub App).
  2. Repo: this monorepo. Branch: main (or whatever).
  3. Build Pack: Dockerfile.
  4. Base Directory: garage-erp (where the Dockerfile lives — relative to repo root).
    • If garage-erp IS the repo root, leave blank.
  5. Dockerfile Location: Dockerfile (default).
  6. Port: 3000.

2. Environment variables

Coolify → Application → Environment Variables. Add:

Key Value
NEXT_PUBLIC_API_URL https://api.reparee.com
NEXT_PUBLIC_SAAS_URL https://reparee.com
NEXT_PUBLIC_GARAGE_HOST_PATTERN *.reparee.com
NODE_ENV production
HOSTNAME 0.0.0.0
PORT 3000
NEXT_TELEMETRY_DISABLED 1

NEXT_PUBLIC_* values are baked into the JS bundle at build time. Changing them requires a redeploy, not just a restart.

3. Domain + TLS

Coolify → Application → Domains → add https://tenant.reparee.com. Coolify auto-provisions Let's Encrypt cert. DNS A record must already point to the Coolify server's public IP.

4. Healthcheck

Coolify → Application → Healthcheck:

  • Path: /api/proxy/health — set this once the backend is reachable; otherwise / works for the first deploy.
  • Port: 3000
  • Interval: 30s
  • Timeout: 10s

5. Build options

  • Build pack: Dockerfile
  • Custom build command: leave blank (Dockerfile handles it)
  • Build args: none required; all envs are runtime

6. Deploy

Click Deploy. Watch build logs:

  • Stage 1 (deps): pnpm install --frozen-lockfile — ~2-4 min.
  • Stage 3 (builder): pnpm --filter @garage/dashboard build — ~3-6 min. Watch for Next.js trace warnings; they are non-fatal.
  • Stage 4 (runner): copies standalone output; tiny.

First build is slow. Subsequent builds reuse Docker layer cache.

7. Smoke test

curl -I https://tenant.reparee.com
# → 200 OK + Set-Cookie not yet set (no session)

# Activation: full flow goes SaaS → /activate/handoff/{token}?ws=&api=
# Cookies expected after redirect: auth_token, auth_user, workspace_uuid, api_base_url

8. CORS / cookies sanity

The dashboard only sets cookies on its own origin (tenant.reparee.com). The Next.js server proxy at /api/proxy/* strips upstream Set-Cookie headers — Laravel cookies never reach the browser. Workspace context is read from cookies on every server-side proxy call.

Verify in browser DevTools after handoff:

  • 4 cookies on tenant.reparee.com, all HttpOnly + SameSite=Strict + Secure.
  • Network tab: all XHR/fetch go to tenant.reparee.com/api/proxy/.... Zero direct calls to api.reparee.com from the browser.

9. Logs

Coolify → Application → Logs tab streams container stdout/stderr. Next.js logs requests as GET / 200 in 45ms etc.

10. Rollback

Coolify → Deployments tab → pick a previous successful deployment → Redeploy.

11. Notes on monorepo

  • The Dockerfile builds only the @garage/dashboard app. @garage/api is built as part of dashboard's prebuild hook (it generates OpenAPI types from postman/collection.json).
  • If you split apps later (e.g. a separate admin app), copy the Dockerfile and change the --filter @garage/dashboard line.
  • output: 'standalone' in apps/dashboard/next.config.mjs is required for the runner stage to work. Do not remove.

12. Cypress / e2e

Out of scope for the runtime container. If you want CI e2e runs:

  • Use Coolify's GitHub Actions integration to run pnpm test:e2e in CI before the deploy webhook fires.
  • Update apps/dashboard/cypress.config.ts to read baseUrl from env (currently hard-coded to https://newgarage.yslootahtech.com).