Railway deployment management for {{PROJECT_NAME}}: CLI, env vars, health checks, troubleshooting, rollback.
Note: Current UI is Next.js on Vercel: https://{{FRONTEND_URL}} (production app) and https://{{STAGING_FRONTEND_URL}} (staging).
Skill Type: Deployment Management For Agent: @shawar-2.0 Platform: Railway (Backend Hosting; Frontend on Vercel)
| Service | URL |
|---|---|
| Frontend (Vercel) | https://{{FRONTEND_URL}} |
| Backend | https://{{BACKEND_URL}} |
| Service | Project ID |
|---|---|
| Backend | {{RAILWAY_PROJECT_ID}} |
| Service | Service ID |
|---|---|
| Backend | cf1c43ee-ca19-4b0f-8321-7fbf6500338d |
| Cron Daily | 91906328-ca49-4ea2-a163-a6aadbae06f9 |
| Cron Chroma | 44d0e76b-2029-4e52-b0b0-4cc34d7d1733 |
# Link to {{PROJECT_NAME}} Backend
railway link {{RAILWAY_PROJECT_ID}}
⚠️ IMPORTANT:
railway linkonly works with interactive login or Account Tokens. It does NOT work with Project Tokens (see CI/CD section below).
| Token Type | Env Variable | Scope | Use Case |
|---|---|---|---|
| Project Token | RAILWAY_TOKEN | Single project/environment | CI/CD redeploys |
| Account Token | RAILWAY_API_TOKEN | All projects in account | Interactive CLI, railway link |
| Team Token | RAILWAY_API_TOKEN | All projects in team | Team automation |
railway linkProject Tokens CANNOT use railway link - they fail with "Unauthorized" because:
railway link tries to authenticate at the account level# ❌ WRONG - fails with "Unauthorized"
- name: Deploy Backend
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN_BACKEND }}
run: |
railway link --project 6e450618-... --service cf1c43ee-...
railway redeploy --service cf1c43ee-... --yes
# ✅ CORRECT - Project Tokens don't need link
- name: Deploy Backend
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN_BACKEND }}
run: railway redeploy --service cf1c43ee-ca19-4b0f-8321-7fbf6500338d --yes
Token URLs:
# Test Project Token
RAILWAY_TOKEN="<project-token>" railway whoami
# Should show project details, NOT "Unauthorized"
# Test Account Token (different env var!)
RAILWAY_API_TOKEN="<account-token>" railway whoami
# Should show "Logged in as <name>"
| Secret Name | Token Type | Project |
|---|---|---|
RAILWAY_TOKEN_BACKEND | Project Token | Mission-Inbox-Backend |
RAILWAY_TOKEN_CRON_DAILY | Project Token | MI-Cron-DailyData |
RAILWAY_TOKEN_CRON_CHROMA | Project Token | MI-Cron-ChromaDB |
| Mistake | Why It Fails | Correct Approach |
|---|---|---|
Using railway link with Project Tokens | Project Tokens can't authenticate at account level | Skip railway link, just use railway redeploy --service <id> |
| Using wrong env var for token type | RAILWAY_TOKEN ≠ RAILWAY_API_TOKEN | Project Tokens → RAILWAY_TOKEN, Account Tokens → RAILWAY_API_TOKEN |
| Assuming token works across workspaces | Tokens are workspace-scoped | Generate token in the SAME workspace as the project |
Trying to debug with railway whoami using wrong var | railway whoami with Project Token may show different info | Use RAILWAY_API_TOKEN for account-level whoami |
| Not copying token immediately | Railway only shows token ONCE | Copy immediately after generation |
Symptom: Unauthorized. Please login with railway login
Diagnosis Steps:
Check token type matches usage:
# Project Token test
RAILWAY_TOKEN="<token>" railway redeploy --service <id> --yes
# Account Token test
RAILWAY_API_TOKEN="<token>" railway whoami
Verify token is valid (not expired/revoked):
Verify workflow doesn't use railway link with Project Tokens:
# If you see this pattern, it's wrong:
run: |
railway link --project ... # ❌ REMOVE THIS
railway redeploy ...
Check GitHub Secret was updated:
Quick Fix Checklist:
railway link from workflowRAILWAY_API_TOKEN env varThis skill enables Railway deployment management including environment configuration, service deployment, health monitoring, and troubleshooting for the {{PROJECT_NAME}} project.
# Install Railway CLI (macOS)
brew install railway
# Or use npm
npm i -g @railway/cli
# Login to Railway
railway login
# Check current user
railway whoami
# Logout
railway logout
# Link to existing project (interactive)
railway link
# Link to specific project by ID
railway link {{RAILWAY_PROJECT_ID}}
# Unlink current directory
railway unlink
# List all projects
railway list
# Check current project status
railway status
# Deploy current directory
railway up
# Deploy without waiting (detached)
railway up --detach
# Deploy specific service (when multiple exist)
railway up --service=<service-name>
# Remove most recent deployment
railway down
# Redeploy latest
railway redeploy
# List all environments
railway environment
# Switch environment
railway environment [env-name]
# Run command with Railway env vars locally
railway run npm start
railway run python app.py
# Open Railway dashboard
railway open
# View deployment logs
railway logs
# View build logs only
railway logs --build
# Follow logs in real-time
railway logs -f
railway logs --follow
# View specific number of lines
railway logs -n 100
railway logs --lines=100
# Filter logs
railway logs --filter="error"
railway logs -f --filter="ERROR"
# Output as JSON
railway logs --json
# List all variables
railway variables
# Get specific variable
railway variables get DATABASE_URL
# Set variable
railway variables set KEY=value
# Delete variable
railway variables delete KEY
# Load from .env file
railway variables set --from-env-file=.env
# SSH into running service
railway ssh
# SSH with full command (from dashboard)
railway ssh --project=<project-id> --environment=<env-id> --service=<service-id>
# Run single command via SSH
railway ssh --command="ls -la"
PORT # Auto-set by Railway
OPENROUTER_API_KEY # LLM API access
ANTHROPIC_API_KEY # Claude API (optional)
ADMIN_TOKEN # Admin authentication
CORS_ORIGINS # Allowed origins (comma-separated)
DATABASE_URL # PostgreSQL connection (if used)
CHROMA_PATH # ChromaDB storage path
uvicorn api:app --host 0.0.0.0 --port $PORT
bash start.sh
Frontend is deployed on Vercel (Next.js). There is no Railway frontend service.
https://{{FRONTEND_URL}}https://{{STAGING_FRONTEND_URL}}Verify code is ready
# Test locally first
railway run python -m pytest
railway run python app.py
Check environment variables
railway link <project-id>
railway variables
Deploy
railway up
Monitor deployment
railway logs -f
Verify health
curl https://{{BACKEND_URL}}/health
railway up for productionCheck build logs first:
railway logs --build
# Verify requirements.txt is complete
pip freeze > requirements.txt
# Check for missing system dependencies
# Add nixpacks.toml if needed
# Create nixpacks.toml in project root
[phases.setup]
nixPkgs = ["python311"]
[phases.install]
cmds = ["pip install -r requirements.txt"]
[start]
cmd = "uvicorn api:app --host 0.0.0.0 --port $PORT"
.railwayignore:node_modules
__pycache__
.git
*.log
.env
.DS_Store
data/raw/
*.csv
# Check if PORT is used correctly
# In Python:
port = int(os.getenv("PORT", 8000))
uvicorn.run(app, host="0.0.0.0", port=port)
# Verify variables are set
railway variables
# Check if deployed after adding variables
# Variables need redeploy to take effect!
railway up
# Test connection
railway run python -c "import os; print(os.getenv('DATABASE_URL'))"
# For external DBs: whitelist Railway IPs or use 0.0.0.0/0
# Check CORS_ORIGINS includes frontend URL
railway variables get CORS_ORIGINS
# Should include:
# https://{{FRONTEND_URL}}
# Check if service is running
railway status
railway logs --tail 50
# Common cause: app crashed on startup
# Check for missing env vars or import errors
After every deployment:
# Check service is running
railway logs --tail 50
# Test health endpoint
curl https://{{BACKEND_URL}}/health
# Test API status
curl https://{{BACKEND_URL}}/api/status
Check Railway dashboard for failed deployment
Review error logs: railway logs --build
If critical, revert via git:
git revert HEAD
git push origin main
# Railway auto-deploys the revert
Railway doesn't have instant rollback like Vercel, so use git:
git log --oneline -5 # Find last good commit
git revert <bad-commit> # Revert bad commit
git push origin main # Push triggers redeploy
{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "NIXPACKS"
},
"deploy": {
"startCommand": "uvicorn api:app --host 0.0.0.0 --port $PORT",
"healthcheckPath": "/health",
"healthcheckTimeout": 100,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 10
}
}
[phases.setup]
nixPkgs = ["python311"]
[phases.install]
cmds = ["pip install -r requirements.txt"]
[phases.build]
cmds = ["echo 'Build complete'"]
[start]
cmd = "uvicorn api:app --host 0.0.0.0 --port $PORT"
python manage.py migrateSee references/quick-reference.md for {{PROJECT_NAME}} deploy commands, endpoint checks, and success criteria.
Date: 2026-01-03
Issue: Railway dashboard settings OVERRIDE railway.json configuration
You might have railway.json with:
{
"build": {
"builder": "NIXPACKS"
}
}
But Railway ignores this if dashboard is configured to use Docker images!
# Check /__version endpoint
curl https://your-app.railway.app/__version | jq '.'
# If response includes "image": "ghcr.io/..." → Railway pulls from GHCR
# If no image field or build logs show Nixpacks → Source build
| Environment | Build Source | Image |
|---|---|---|
| Production | GHCR | {{DOCKER_IMAGE}}:latest |
| Staging | GHCR | {{DOCKER_IMAGE}}:staging |
Both use Docker images from GHCR, NOT Nixpacks source builds.
# 1. Build and push to GHCR
- name: Build and push image
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/org/app:latest
# 2. Trigger Railway to pull new image
- name: Deploy
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: railway redeploy --service <id> --yes
# Check the /__version endpoint
curl https://your-app.railway.app/__version | jq '.'
# Verify git_sha matches your latest commit
# Verify image field shows expected GHCR tag
| Symptom | Cause | Fix |
|---|---|---|
| Old code running after deploy | GHCR push failed, Railway used cached image | Re-run workflow, check GHCR for new tag |
/__version shows wrong commit | Image tag mismatch | Verify workflow pushed correct SHA tag |
| Railway builds from source | Dashboard set to GitHub Repo | Change to Docker Image in dashboard |
Date: 2026-01-03
Issue: staging-verified check can fail if it runs before staging build completes
GitHub Actions runs all jobs in parallel by default. The staging-verified check might:
# .github/workflows/staging-gate.yml