# TwentyCRM Deployment for DRE ## Server - Host: Core VPS (netcup, 8C/15G, Debian 13) - URL: https://crm.debtrecoveryexperts.com - Deploy: Docker Compose under /root/docker/twenty/ - Port: 3001 (mapped from container port 3000) ## Docker Compose Stack - twenty-server (NestJS backend) - twenty-worker (BullMQ async worker) - twenty-db (PostgreSQL 16) - twenty-redis (Redis cache) ## Env Vars (/.env in project dir) - `SERVER_URL` MUST be set to the public URL (e.g. https://crm.debtrecoveryexperts.com) - `REACT_APP_SERVER_BASE_URL` MUST match `SERVER_URL` — injected into frontend build at runtime - `ENCRYPTION_KEY` generated on first deploy - `PG_DATABASE_PASSWORD` set on first deploy ## API Access - API key stored in ~/.hermes/.env as `TWENTY_CRM_API_KEY` - GraphQL endpoint: POST https://crm.debtrecoveryexperts.com/graphql (standard queries) - Metadata endpoint: POST https://crm.debtrecoveryexperts.com/metadata (schema mutations) - REST endpoint: POST https://crm.debtrecoveryexperts.com/rest/{object} ## Custom Objects Created (DRE Data Model) - Claims (claim) — Claim Number, Amount, Debt Type, Current Tier, Status, State, Date Filed, AI Score, Description - Debtors (debtor) — Business Name, Contact Name, Email, Phone, Address, Business Type, Notes - Payments (payment) — Payment Amount, Date, Method, DRE Fee, Costs Deducted, Net to Client - Case Notes (caseNote) — Content, Timestamp ## Relationships (via GraphQL metadata API) The correct mutation format uses `relationCreationPayload` inside the `field` object: ```graphql mutation { createOneField(input: { field: { name: "debtorRelation", label: "Debtor", type: RELATION, objectMetadataId: "", relationCreationPayload: { type: "MANY_TO_ONE", targetObjectMetadataId: "", targetFieldLabel: "Claims", targetFieldIcon: "IconBriefcase" } } }) { id name } } ``` The `relationCreationPayload` is nested inside the `field` object, NOT at the top level of the input. This is different from what the error messages suggest. ## First-time Setup 1. Visit https://crm.debtrecoveryexperts.com 2. Click "Continue with Email" — magic link sent to inbox 3. Create workspace → admin account is the first workspace member 4. Generate API key from Settings → API Keys ## Authentication (Cloudflare Access) - CRM is behind Cloudflare Access (proxy enabled) - Users authenticate via email magic link through Cloudflare - Optional 2FA (TOTP) can be enabled per-user from Cloudflare dashboard - NOT behind Caddy basic_auth — that was removed in favor of Access ## Cost - Software: $0 (AGPL self-hosted) - Infrastructure: part of existing VPS - Cloud Access: free up to 50 users