SoConnective

Operations

Runbook 05 — Platform apps (backend, CRM, portal)

Domains, Coolify apps, the auth flow, deploy steps, and the real gotchas.

Domains -> apps

DomainAppRole
soconnective.comapps/webPublic website
backend.soconnective.com (also cms.)apps/cms (Payload)Engine: data, API, auth, multi-tenant, CMS, connections
crm.soconnective.comapps/crmAgency CRM (Next.js + shadcn/ui), consumes the backend API
portal.soconnective.comapps/portal (future)Client portal
dashboard.soconnective.comlegacy PHPRetires when the CRM is complete

Coolify apps

  • Each app is a Coolify application: base_directory = its apps/<name> folder, build pack nixpacks, port 3000, deployed from Forgejo main.
  • CRM env: PAYLOAD_URL = https://backend.soconnective.com (used for server-side fetches).
  • Payload (apps/cms) serves both backend. and cms.; serverURL/CORS/CSRF include backend., cms. and crm.
  • Payload root / redirects to /admin (via next.config redirects).

Auth (CRM <-> backend)

  • The team signs in at crm./login -> a server action POSTs to backend /api/users/login -> the returned token is stored in an httpOnly cookie on the crm domain.
  • Server components fetch the backend API with Authorization: JWT <token> (server-to-server, no CORS needed).
  • Mutations run through server actions (which hold the token). A middleware guards all routes (redirects to /login without a token).

Deploy

  • Push to main -> the docs site auto-deploys (Forgejo webhook). Other apps deploy on demand:
  • GET {coolify}/api/v1/deploy?uuid=<app-uuid>&force=true (token in fs-secrets).

Gotchas (real)

  1. Git URL mangled to SSH when creating an app via the API -> clone fails (does not appear to be a git repository). Fix: PATCH git_repository to the full https://feedback:<token>@git.soconnective.com/feedback/soconnective.git.
  2. OOM during build (the "Collecting build traces" step) on the 8 GB VPS under load -> retry the deploy (usually succeeds on the 2nd attempt). Long-term: more swap or a dedicated build.
  3. TLS cert: after a new subdomain's DNS points to the VPS, restart the app so Traefik requests the Let's Encrypt certificate.
  4. DNS: new subdomains must have an A record -> 216.250.119.216 (the VPS). An old Plesk box (216.250.126.64) still answers stale records with an expired certificate.
Previous
Deployment & Operations