# Twenty (Railway) agent runbook

This folder defines how we run **Twenty CRM** on Railway using GitOps.

## Desired outcome

- One Railway **project** containing:
  - `twenty-web` service (HTTP)
  - `twenty-worker` service (background jobs)
  - `Postgres` database service
  - `Redis` database service
- Deployments happen automatically from GitHub pushes (service source repo is this repo).

## Repo layout (source of truth)

- `twenty/web/`
  - `Dockerfile` (pins image + start command)
  - `railway.json` (config-as-code for the web service)
- `twenty/worker/`
  - `Dockerfile` (pins image + worker start command)
  - `railway.json` (config-as-code for the worker service)
- `twenty/railway/`
  - `config.json` (Railway project + environment + service names)
- `twenty/.env.example`
  - Canonical list of env vars + docs.

## Railway service settings (must be set in UI)

Railway only supports config-as-code at the **service** level (`railway.json` / `railway.toml`).
Project creation, database provisioning, and custom domains are managed in Railway UI.

Create two services from this repo:

### Service: `twenty-web`
- Source repo: this repo
- Root directory: `twenty/web`
- Config-as-code path: `/twenty/web/railway.json`
- Networking:
  - Enable public networking
  - Add custom domain: `cultscale.org`

### Service: `twenty-worker`
- Source repo: this repo
- Root directory: `twenty/worker`
- Config-as-code path: `/twenty/worker/railway.json`
- No public domain needed

### Database services
- Add Postgres database service (name it `Postgres`)
- Add Redis database service (name it `Redis`)

## Variables (GitOps approach)

We keep the variable *names* + docs in `twenty/.env.example`.
We apply/update variables using the **Railway CLI** directly (no repo scripts).

- Web service name in Railway: `Twenty`
- Worker service name in Railway: `Twenty Worker`

Recommended wiring:
- `PG_DATABASE_URL=${{Postgres.DATABASE_URL}}`
- `REDIS_URL=${{Redis.REDIS_URL}}`

Never commit secrets; do not save variable dumps into the repo.

### Railway-provided vars (do NOT set manually)
- `PORT`
- any `RAILWAY_*`

### Required vars (set in BOTH services)
- `PG_DATABASE_URL`
- `REDIS_URL`
- `APP_SECRET`
- `SERVER_URL`
- `FRONTEND_URL`
- `STORAGE_TYPE`

### AI enablement (set in BOTH services)
AI features become available when at least one provider key is configured:
- `OPENAI_API_KEY` (or)
- `ANTHROPIC_API_KEY` (or)
- `XAI_API_KEY`

Also ensure the workspace feature flag is enabled in Postgres:
- `IS_AI_ENABLED` (stored in the workspace schema `featureFlag` table; not an env var)

Optional (recommended) for sandboxed code execution:
- `CODE_INTERPRETER_TYPE=E2B`
- `E2B_API_KEY`

### Recommended variable wiring (reference vars)

Prefer Railway reference variables so DB/Redis connection strings stay in sync:
- `PG_DATABASE_URL=${{Postgres.DATABASE_URL}}`
- `REDIS_URL=${{Redis.REDIS_URL}}`

(Exact exported variable names can differ; confirm in the Postgres/Redis service Variables list and adjust.)

## Custom domain + DNS (cultscale.org)

1. Add `cultscale.org` to the `twenty-web` service (Railway UI).
2. Railway provides a target like `xxxx.up.railway.app`.
3. Update `dns/zones/cultscale.org.yaml`:
   - set the apex `ALIAS` record value to that `*.up.railway.app.` target.
4. Validate DNS changes: `cd dns && make validate`.

## How to ask Copilot to change things

Be specific about which service:
- “Update `twenty/web` start command / image tag”
- “Add a new optional env var to `twenty/.env.example`”
- “Change DNS ALIAS for `cultscale.org` to the new Railway target”

If you paste the exact variable names Railway exposes for your Postgres + Redis services, we’ll lock the reference-variable wiring to match exactly.
