---
title: "Deploy Twenty CRM — Self-Hosted, Server + Worker Wired Right [Updated Sep'26]"
description: "Self-host Twenty CRM — Salesforce alternative, no per-seat fees"
category: "CMS"
url: https://railway.com/deploy/twenty-crm-self-hosted
---

# Deploy Twenty CRM — Self-Hosted, Server + Worker Wired Right [Updated Sep'26]

Self-host Twenty CRM — Salesforce alternative, no per-seat fees

**[Deploy Twenty CRM — Self-Hosted, Server + Worker Wired Right [Updated Sep'26] on Railway](https://railway.com/template/twenty-crm-self-hosted)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/twenty-crm-self-hosted/manifest.json

- **Creator:** SilverBanana
- **Category:** CMS

## Template content

### Twenty https://raw.githubusercontent.com/twentyhq/twenty/6fd8dab55243cda291fa45f896caaa9d5e5160b8/packages/twenty-chrome-extension/public/logo/32-32.svg

- **Image:** twentycrm/twenty:latest

### Postgres https://devicons.railway.app/i/postgresql.svg

- **Image:** ghcr.io/railwayapp-templates/postgres-ssl:18

### Twenty Worker https://raw.githubusercontent.com/twentyhq/twenty/6fd8dab55243cda291fa45f896caaa9d5e5160b8/packages/twenty-chrome-extension/public/logo/32-32.svg

- **Image:** twentycrm/twenty:latest

### Redis https://cdn.sanity.io/images/sy1jschh/production/0ce0bfdcfbdbf69662b1116671f97c2dd788b655-157x157.svg

- **Image:** redis:8.2
- **Start command:** `/bin/sh -c "rm -rf $RAILWAY_VOLUME_MOUNT_PATH/lost+found/ && exec docker-entrypoint.sh redis-server --requirepass $REDIS_PASSWORD --save 60 1 --dir $RAILWAY_VOLUME_MOUNT_PATH"`

## Buckets

- **Bucket**

## Documentation

# Deploy and Host Twenty on Railway

Twenty is a modern open-source CRM — a self-hosted Salesforce alternative for managing companies, contacts, opportunities, and custom objects, with a clean Notion-like interface, Kanban pipelines, and a full REST and GraphQL API. This template deploys it the way Twenty is built to run: the server and background worker wired together over Redis with a shared secret, the public URL set to avoid the login-loop trap, and Postgres and file storage configured — so you get a working CRM, not a half-deployed one that can't log in or run workflows.

---

## What This Template Deploys

| Service | Purpose |
| --- | --- |
| **Twenty Server** | The API, React frontend, schema, and migrations (port 3000) |
| **Twenty Worker** | Background jobs — email sync, workflows, and cron (BullMQ) |
| **PostgreSQL** | Companies, contacts, opportunities, and custom objects |
| **Redis** | The job queue and cache the worker runs on |

All connect over Railway's private network. The server and worker run the same image as two processes, backed by PostgreSQL for CRM data and Redis for the job queue, with file storage for avatars and attachments — a complete, working CRM stack.

---

## About Hosting

Twenty is a two-process application, and getting that architecture right is the difference between a CRM that works and one that half-loads — this template handles it.

**Server and worker are one image doing two jobs — with one shared secret.** Twenty runs the same image as a server (the API, React frontend, and migrations) and a separate worker (email sync, workflow runs, and cron via BullMQ). The worker isn't optional: without it, background jobs, email, and automations silently never run. Both must share an identical `APP_SECRET`/`ENCRYPTION_KEY` — it encrypts secrets at rest and signs sessions, so a mismatch breaks logins and data. This template generates one secret and wires it to both.

**`SERVER_URL` must match your domain — or login loops forever.** This is the most common Twenty failure: if `SERVER_URL` (and the frontend base URL) don't exactly match the HTTPS domain you access Twenty on, the login page redirects in an infinite loop. This template sets it to your Railway public domain, so authentication works on the first try instead of trapping you at the sign-in screen.

**Redis is required — the worker won't run without it.** Twenty's background queue runs on Redis (BullMQ), so a missing `REDIS_URL` makes the worker exit immediately and email sync, workflows, and scheduled jobs never fire. This template wires Redis over the private network, so the queue works out of the box.

**File storage — local volume or S3.** Avatars and attachments need somewhere to live: this template configures storage (a persistent volume with `STORAGE_TYPE=local`, or S3-compatible object storage via `STORAGE_TYPE=s3` and the `STORAGE_S3_*` variables — MinIO or a Railway Bucket work without extra config). Either way, uploads survive redeploys. There's no env-var admin: open your Railway domain and Twenty presents a Get Started wizard to create the workspace admin; members join by invite. Logs are set to `error,warn`, since Twenty's default verbosity floods a platform's log rate limit on a quiet instance.

Typical cost: **~$10–20/month** on Railway for the four services — server and worker use ~0.5 GB RAM each at idle, so a small team fits a modest plan; scale up past 10 active users. Twenty is AGPL-3.0 and free, with no user, record, or feature caps — versus Twenty's own cloud at $9+/user/month and Salesforce's per-seat pricing.

---

## How It Compares

| | Twenty (self-hosted) | Salesforce | HubSpot | Twenty Cloud |
| --- | --- | --- | --- | --- |
| Cost model | Flat infra | Per seat (high) | Freemium + per seat | Per user/month |
| Custom objects | Yes | Yes | Limited | Yes |
| API | REST + GraphQL | Yes | Yes | REST + GraphQL |
| Modern UX | Yes (Notion-like) | Dated | Yes | Yes |
| Data ownership | Full — your infra | Vendor | Vendor | Vendor |
| Self-hostable | Yes | No | No | No |

Salesforce and HubSpot are powerful but expensive per seat and keep your customer data on their servers. Twenty's own cloud is convenient but still per-user. Twenty self-hosted's edge is a modern, developer-friendly CRM — custom objects, Kanban pipelines, and REST/GraphQL APIs — at flat infrastructure cost with no per-seat fees, on infrastructure you own.

---

## Deploy in Under 5 Minutes

1. Click **Deploy on Railway** — the server, worker, PostgreSQL, and Redis build and wire together (~4 minutes)
2. Confirm `APP_SECRET` is shared by server and worker, and `SERVER_URL` matches your Railway domain
3. Wait for the server to run migrations and the worker to connect to Redis
4. Open your Railway domain and complete the Get Started wizard to create your admin
5. Add companies, contacts, and a pipeline, or import contacts via CSV or the API

Invite teammates from settings — the first account is the workspace admin.

---

## Common Use Cases

- **Sales pipeline of record** — companies, people, and opportunities in Kanban stages, replacing a spreadsheet or seat-metered CRM
- **Product-to-CRM sync** — push signups, trials, and usage into custom objects over the REST or GraphQL API
- **Internal ops database** — track vendors, applicants, or assets as custom objects with views and an API
- **Salesforce/HubSpot replacement** — a modern CRM without per-seat licensing

---

## Configuration

| Variable | Required | Description |
| --- | --- | --- |
| `APP_SECRET` | Generated | Encrypts secrets and signs sessions — identical on server and worker |
| `SERVER_URL` | Required | Your Railway HTTPS domain — must match, or login loops |
| `PG_DATABASE_URL` | Auto-injected | PostgreSQL connection for CRM data |
| `REDIS_URL` | Auto-injected | Redis for the BullMQ job queue — the worker needs it |
| `STORAGE_TYPE` / `STORAGE_S3_*` | Configurable | `local` on a volume, or `s3` for object storage |

> **One shared secret, and match the URL.** `APP_SECRET` must be identical on server and worker (it signs sessions and encrypts data), and `SERVER_URL` must equal your Railway domain or login redirects infinitely. This template wires both correctly.

> **Redis and the worker are required.** The worker runs email sync, workflows, and cron over Redis (BullMQ) — without them those never fire. Both are wired here, and file storage is set for avatars and attachments.

---

## Dependencies for Twenty Hosting

- Railway account — ~$10–20/month for the four services, scaling with team size
- PostgreSQL and Redis (both included and wired via Railway references)
- File storage — a volume (local) or an S3-compatible bucket for uploads
- A modern browser to run the CRM; CSV or the API to import contacts

### Deployment Dependencies

- [Twenty GitHub Repository](https://github.com/twentyhq/twenty)
- [Twenty Documentation](https://twenty.com/developers)
- [Twenty Self-Hosting Guide](https://twenty.com/developers/section/self-hosting)
- [Railway Private Networking](https://docs.railway.com/guides/private-networking)

### Implementation Details

The template deploys Twenty as two processes from the same pinned `twentycrm/twenty` image: `twenty-server` (the NestJS API, React frontend, schema setup, and migrations on port 3000) and `twenty-worker` (background jobs — email sync, calendar, workflow triggers, and cron — via BullMQ over Redis), both wired to a shared PostgreSQL and Redis over Railway's private network. Both processes require an identical `APP_SECRET`/`ENCRYPTION_KEY`, which encrypts secrets at rest and signs sessions; the template generates one and applies it to both, since a mismatch breaks authentication and stored data.

`SERVER_URL` must match the public HTTPS domain exactly, or the frontend login redirects in an infinite loop — the most common self-hosted Twenty failure — so it is set to the Railway domain. Redis is mandatory for the worker (a missing `REDIS_URL` causes it to exit), and file storage for avatars and attachments is configured either on a volume (`STORAGE_TYPE=local`) or via S3-compatible object storage (`STORAGE_TYPE=s3` with `STORAGE_S3_*`), where MinIO or a Railway Bucket work without extra configuration because Twenty's S3 driver uses path-style addressing.

On first load the public domain presents a Get Started wizard that creates the sole workspace admin; members join by invite. Log verbosity is set to `error,warn`, as Twenty's default output exceeds the platform's log rate limit on a quiet instance. A `/healthz` check guards the public service, and PostgreSQL and file storage are the backup targets.

---

## Frequently Asked Questions

**Why does Twenty's login loop forever?** Almost always `SERVER_URL` — it must exactly match the HTTPS domain you access Twenty on, or the frontend redirects endlessly at sign-in. This template sets it to your Railway domain, so login works on the first try.

**Why does the worker need Redis?** Twenty's background queue runs on Redis (BullMQ), so a missing `REDIS_URL` makes the worker exit and email, workflows, and scheduled jobs never fire. Redis is included and wired here.

**Can I import my existing contacts?** Yes — Twenty supports CSV import for contacts and companies, and its REST and GraphQL APIs let you sync data programmatically from other systems.

---

## Why Deploy Twenty on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Twenty on Railway you get a modern open-source CRM with the hard parts solved — server and worker wired over Redis with a shared secret, the public URL set so login works, and Postgres and file storage configured. Manage companies, contacts, and pipelines with no per-seat fees, self-hosted on infrastructure you own.

## Similar templates

- [Libredesk - Complete Setup](https://railway.com/deploy/libredesk-complete-setup) — Complete self-hosted omnichannel customer support desk.
- [Paperless-ngx](https://railway.com/deploy/paperless-ngx-3) — Paperless-ngx — document management with OCR and full-text search
- [Instatic CMS - Postgres](https://railway.com/deploy/instatic-cms-postgres) — Design, build and manage powerful static sites from state-of-the-art CMS

Open this page in a browser: https://railway.com/deploy/twenty-crm-self-hosted
