Third Twenty CRM Stack Deployed — This Time for Ourselves
The per-client Twenty deployment runbook just ran a third time — for The Lossless Group's own CRM. Project creation to healthy /healthz in under ten minutes, zero new failure modes.
Why Care?
We sell clients on self-hosted stacks — their own CRM, their own data, their
own Railway project, no per-seat SaaS tax. If we believe that pitch, our own
consulting org should run on the same shape. As of today it does: lossless
is the third Twenty CRM stack deployed from docs/twenty/setup.md, after
reach-edu and palmer-ai.
The quieter win is what didn't happen. The first deployment (reach-edu) was
the shakedown cruise — it discovered the PORT vs NODE_PORT healthcheck
trap, the seconds-not-milliseconds timeout, the ENCRYPTION_KEY migration.
The second (palmer-ai) confirmed the fixes. The third ran the runbook nearly
verbatim: project → five services → variables → redeploy → healthy in one
pass. That's what a runbook maturing looks like.
What's New?
Railway project
losslessin The Lossless Group workspace: twenty-server, twenty-worker, twenty-postgres (volumed), twenty-redis (noeviction), and atwenty-storagebucket — same five-part topology, same pinned imagetwentycrm/twenty:v2.24.1as the other two stacks.Live at
https://twenty-server-production-753f.up.railway.app— healthz 200, login page verified by browser-drive. Admin account creation (Gate 1) is pending Michael's own login.client-stacks/lossless/folder of record (gitignored): stack.md, secretspec.toml, recovery.env, restore-runbook.md — mirroring the reach-edu reference shape.Two deltas logged in
docs/twenty/setup.mdfor future runs (below).
Under the Hood
Two small deltas surfaced, both tooling-shaped rather than Twenty-shaped:
Image services deploy at creation, before variables exist. Creating a service from an image kicks off an immediate deploy with an empty environment. Setting variables with
--skip-deploysafterward means the running deploy never sees them — every service needed an explicitrailway redeployonce variables landed. Postgres is the interesting case: its first boot withoutPOSTGRES_PASSWORDfails harmlessly, and the redeploy runs a clean initdb into thePGDATAsubdir.The Railway MCP
add_reference_variabletool rejects embedded references. It requires the whole value to start with${{, so a composite likepostgres://postgres:${{twenty-postgres.POSTGRES_PASSWORD}}@…doesn't pass validation. Plainset_variablesaccepts the template syntax and Railway resolves it fine — reference-variable wiring intact, dependency arrows and all.
Secrets discipline held: bucket credentials went CLI → file → Railway
variables without ever printing to the session transcript, and the recovery
copy landed in the gitignored client-stacks/lossless/twenty/.env.
What's Next
Gate 1: Michael creates the admin account and workspace, live.
Real API key (Settings → APIs, not the 2-hour playground token) →
twenty-interfaceskill scoped to this instance.Phase 3 backups: R2 bucket
lossless+pg-dump-twentysingle-shot cron.Phase 5: a
*.didi.shsubdomain via the [[custom-domain-cutover]] playbook.
Files changed
docs/twenty/setup.mdchangelog/2026-07-27_01.md