Skip to main content

EchoHuman Twenty CRM

Twenty is an open-source CRM. EchoHuman's instance is a fully self-contained Docker Compose stack on VM700.

Public URL

https://crm.echohuman.org

Stack

/opt/stacks/echohuman-twenty/ on VM700 — 4 containers:

ContainerRole
echohuman-twenty-server-1Web server + API (7010→3000)
echohuman-twenty-worker-1Background jobs
echohuman-twenty-db-1Local Postgres 16
echohuman-twenty-redis-1Redis

First-Boot Time

~25–35 minutes. The entrypoint runs DB init, migrations, cache flush, upgrade, cron registration before binding port 3000. Container shows unhealthy throughout — this is normal.

Key Config

/opt/stacks/echohuman-twenty/.env:

PG_DATABASE_URL=postgres://twenty:<pass>@db:5432/default
REDIS_URL=redis://redis:6379
SERVER_URL=https://crm.echohuman.org
APP_SECRET=<base64-44-chars>
STORAGE_TYPE=local

Use env_file: .env in compose — never ${APP_SECRET} interpolation.

Known Blockers (resolved)

  1. APP_SECRET empty — shell env overrides ${VAR} interpolation. Fixed with env_file:.
  2. Empty core schema loop — partial migration left 0 tables. Fixed with DROP SCHEMA core CASCADE then restart.
  3. CT320 connection — EchoHuman must use its own local DB, not CT320.

Operations

# Status
docker ps --filter name=echohuman-twenty

# Watch startup
docker logs echohuman-twenty-server-1 -f 2>&1 | grep -E '\[Nest\]|ERROR'

# Check migration (expect 61 tables)
docker exec echohuman-twenty-db-1 psql -U twenty -d default \
-c 'SELECT count(*) FROM information_schema.tables WHERE table_schema=chr(99)||chr(111)||chr(114)||chr(101);'