Deploy to Railway — SKILL.md

Raw skill file that agents receive when using this skill

Download
---
name: "Deploy to Railway"
description: "Full deployment workflow for Railway — init project, add Postgres, set env vars, deploy, configure domains. Use when deploying FastAPI, Next.js, Express, or any web app to Railway hosting."
version: "1.0.0"
author: "skynet"
category: "infrastructure"
agents: ["claude-code", "codex", "gemini"]
tags: ["railway", "deploy", "hosting", "postgres", "cli"]
tools_required: ["shell"]
---

# Deploy to Railway

# Deploy to Railway

Use this skill when deploying a web application (FastAPI, Next.js, Express, etc.) to Railway with optional Postgres, Redis, or other add-ons.

## Prerequisites

- Railway CLI installed and authenticated: `railway whoami` should return `worklocalinc`
- If not installed: `npm install -g @railway/cli && railway login`
- Project source code ready with a valid Dockerfile or supported runtime

## Quick Reference Table

| Task | Command |
|------|---------|
| Check auth | `railway whoami` |
| Init new project | `railway init` |
| Link existing project | `railway link` |
| Add Postgres | `railway add -d postgres` |
| Add Redis | `railway add -d redis` |
| Set env var | `railway variables set KEY=value` |
| Set multiple vars | `railway variables set K1=v1 K2=v2` |
| List env vars | `railway variables` |
| Deploy (detached) | `railway up --detach` |
| View logs | `railway logs` |
| Check status | `railway status` |
| Get public domain | `railway domain` |
| Add custom domain | `railway domain add api.example.com` |
| Force redeploy | `railway redeploy` |
| Switch active service | `railway service <name>` |
| Open dashboard | `railway open` |
| List projects | `railway list` |

## Core Workflows

### Workflow 1: Deploy a New App

1. Initialize the project:
```bash
cd /path/to/project
railway init
# Select "Empty Project" or link to existing
```

2. Add Postgres (if needed):
```bash
railway add -d postgres
```
This auto-sets `DATABASE_URL`, `DATABASE_PUBLIC_URL`, `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE`.

3. Set environment variables:
```bash
railway variables set NODE_ENV=production
railway variables set SECRET_KEY=$(openssl rand -hex 32)
```

4. Deploy:
```bash
railway up --detach
```
Railway auto-detects runtime: Dockerfile → Docker build; `package.json` → Node.js (Nixpacks); `requirements.txt` / `pyproject.toml` → Python (Nixpacks).

5. Get public URL:
```bash
railway domain
```

6. Verify:
```bash
railway status
railway logs
```

### Workflow 2: Link Existing GitHub Repo

```bash
railway link
# Select project from list
railway add --repo worklocalinc/<repo-name>
railway up --detach
```

Verify: `railway status` shows "ACTIVE" and the deploy URL.

### Workflow 3: Add Custom Domain

```bash
railway domain add api.myapp.com
# Railway outputs CNAME target
```

Then add a CNAME DNS record pointing `api.myapp.com` to the Railway-provided target. Verify with:
```bash
dig api.myapp.com CNAME
```

### Workflow 4: Multi-Service Projects

```bash
# Switch between services
railway service backend
railway logs

railway service frontend
railway logs
```

### Workflow 5: FastAPI or Next.js Specific

**FastAPI:**
```
# Procfile: web: uvicorn main:app --host 0.0.0.0 --port $PORT
railway variables set PORT=8000
railway up --detach
```

**Next.js:**
```bash
railway variables set PORT=3000
railway up --detach
```

## Common Patterns

**Deploy with all vars in one shot:**
```bash
railway variables set NODE_ENV=production SECRET_KEY=$(openssl rand -hex 32) PORT=3000
railway up --detach && railway logs --tail
```

**For Prisma projects:**
- Use internal `DATABASE_URL` in app (private networking, no egress cost)
- Use `DATABASE_PUBLIC_URL` only for external access (local migrations)

## Troubleshooting

- **Symptom**: Build fails with Nixpacks errors
  **Cause**: Missing start command or incorrect runtime detection
  **Fix**: Add a `Procfile` (e.g. `web: uvicorn main:app --host 0.0.0.0 --port $PORT`) or a `Dockerfile`. Run `railway logs` to see the exact error.

- **Symptom**: App starts but requests fail / port not responding
  **Cause**: App not listening on `0.0.0.0:$PORT` — Railway injects `$PORT`
  **Fix**: Ensure your app binds to `0.0.0.0` on `$PORT`, not `localhost` or a hardcoded port.

- **Symptom**: DB connection refused from within Railway service
  **Cause**: Using `DATABASE_PUBLIC_URL` inside Railway (routes externally, slower)
  **Fix**: Use `DATABASE_URL` (internal private network) for in-Railway services.

- **Symptom**: Deploy hangs and never returns
  **Cause**: Missing `--detach` flag or the build is genuinely stuck
  **Fix**: Ctrl-C, then run `railway redeploy` to force a fresh build.

- **Symptom**: `railway link` shows wrong project or no projects
  **Cause**: CLI not authenticated or directory not associated
  **Fix**: Run `railway whoami` to verify auth. Run `railway link` and select the correct project from the list.

## References

- Railway docs: https://docs.railway.com
- Railway CLI reference: https://docs.railway.com/guides/cli
- James's Railway account: `worklocalinc`

curl -s https://skills.skynet.ceo/api/skills/deploy-to-railway/skill.md