Skip to main content
Coda ships with three Railway scripts. Production also enables RBAC, so the deploy needs one extra step: paste a public key from AgentOS into your env.

Prerequisites

Step 1: Provision the project

Use .env.production to keep production credentials separate from local dev:
cp .env .env.production
Then run:
./scripts/railway_up.sh
This script:
  1. Creates a Railway project called coda.
  2. Adds a pgvector service with a persistent volume at /var/lib/postgresql/data.
  3. Creates the coda application service and forwards every env var from your shell (OPENAI_API_KEY, GITHUB_ACCESS_TOKEN, SLACK_*, TRIAGE_CHANNEL, DIGEST_CHANNEL, JWT_VERIFICATION_KEY, DB_*).
  4. Deploys the app and assigns a public domain.
Copy the Railway domain from the output. The app will crash-loop until Step 2 lands. That’s expected. Production rejects all requests until a JWT_VERIFICATION_KEY is set.

Step 2: Get a JWT key from AgentOS

The key comes from AgentOS:
  1. Open os.agno.com and log in.
  2. Click Add OSLive, paste your Railway URL, click Connect.
  3. Go to Settings and click Generate key pair.
  4. Copy the public key.
  5. Paste it into .env.production:
JWT_VERIFICATION_KEY=-----BEGIN PUBLIC KEY-----
MIIBIjANBgkq...
-----END PUBLIC KEY-----
No quotes needed. The sync script handles the multiline PEM block.

Step 3: Push env and redeploy

./scripts/railway_env.sh
./scripts/railway_redeploy.sh
railway_env.sh reads .env.production and pushes every variable to the Coda service. Safe to run repeatedly. railway_redeploy.sh triggers a fresh build.

Verify

curl https://your-coda.up.railway.app/health
# {"status":"ok"}
Then talk to Coda through the AgentOS UI you connected in Step 2.

Update Slack to point at production

If you set up Slack against an ngrok URL, swap it for your Railway URL:
  1. Open your Slack app at api.slack.com/apps.
  2. Go to Event Subscriptions.
  3. Update the Request URL to https://your-coda.up.railway.app/slack/events.
  4. Wait for the green Verified check, then Save Changes.
You can stop ngrok now. Slack delivers events to Railway from now on.

Operations

TaskCommand
Tail logsrailway logs --service coda
Open the dashboardrailway open
Run a command in the containerrailway ssh --service coda
Sync env after a .env.production change./scripts/railway_env.sh
Redeploy after a code change./scripts/railway_redeploy.sh
Adjust CPU, memory, and replicas in railway.json.

Run local and production in parallel

If Coda is already deployed and you want to keep iterating locally, you’ll need a separate Slack app. Each Slack app delivers events to one URL.
  1. Create a second Slack app called “Coda Dev” in your workspace using the same manifest from Connect Slack.
  2. Copy your .env to .env.local. Replace SLACK_TOKEN and SLACK_SIGNING_SECRET with the dev app’s values.
  3. Point the Coda Dev app’s Request URL at your ngrok URL.
  4. Run locally with the local env file:
docker compose --env-file .env.local up -d --build
Production keeps using .env.production and the production Slack app. Local uses .env.local and Coda Dev. Both work independently. Add .env.local to .gitignore if it isn’t already.

Next

Add scheduled tasks →