Deploy Twenty CRM | Server, Worker, Postgres and Redis, All Pinned
Server, worker, Postgres and Redis. Pinned, and the worker actually runs.
Postgres
Just deployed
/var/lib/postgresql/data
Twenty worker
Just deployed
Redis
Just deployed
/data
Twenty
Just deployed
/app/packages/twenty-server/.local-storage
Twenty CRM
The open-source CRM, self-hosted: server, background worker, Postgres and Redis. Every image pinned.
What you get
Four services wired together the way Twenty's own compose file does it, but for this platform:
- Server — the API and the app, on a volume for uploaded files
- Worker — the background job runner, on the same image with
yarn worker:prod - Postgres 16 and Redis 8, both on their own volumes
The worker is the part people skip. Without it, jobs queue up in Redis and nothing runs them: no email sync, no calendar sync, no cron. It is a separate service here because that is what it is.
Details worth knowing
- Migrations run on the server, not the worker. The worker sets
DISABLE_DB_MIGRATIONSandDISABLE_CRON_JOBS_REGISTRATION, so two services starting at once cannot both try to migrate the same database. - The worker shares the server's
APP_SECRETby reference, not a second generated value. They have to match, and a template that generated two would look fine and fail in a way that is hard to trace. - Redis binds both IPv4 and IPv6. The private network here is IPv6, and the default Redis config listens on neither usefully.
- Logs are set to
error,warn. Twenty at default verbosity exceeds the platform's log rate limit on a quiet instance — seen while testing this, with hundreds of messages dropped per second.
Verified
Deployed from this template: /healthz returns status: ok, the app is served,
the REST API answers unauthenticated calls with 403 rather than a 404, and the
worker's own log shows it processing jobs off the cron-queue through BullMQ —
which only happens if server, Redis and worker are all talking.
The first sign-up happens in the browser, at the domain — that part is a UI flow and was not driven here.
Configuration
Nothing to fill in. APP_SECRET and both database passwords are generated.
SERVER_URL follows the public domain.
Files are stored on the server's volume (STORAGE_TYPE=local). For S3, set
STORAGE_TYPE=s3 and the STORAGE_S3_* variables from Twenty's documentation.
Twenty is by Twenty PBC, AGPL-3.0. This template only configures their published images: https://twenty.com
Template Content
Postgres
postgres:16.11-alpineTwenty worker
twentycrm/twenty:v2.24.1Redis
redis:8.6.5-alpineTwenty
twentycrm/twenty:v2.24.1