πŸ“– MUTX Docs
GitHubΒ·mutx.dev
Welcome
Manifesto
Whitepaper
Roadmap
Documentation Hub
Autonomous Agent Team
MUTX Infrastructure
Python SDK
Support
Contributing
Security Policy
Licensing
Contributor Covenant Code of Conduct
AGENTS.md
App Dashboard
Changelog Status
Claim to Reality Gap Matrix
Governance
Migration Runbook
Monitoring
Mutation Testing
OTel
Overview
Quickstart
Surface Matrix
Technical Whitepaper
Webhook Governance
  1. Docsβ€Ί
  2. Welcome

Railway Deployment#

Deploy to Railway for managed hosting.

Railway Setup#

1. Install Railway CLI#

# macOS
brew install railway

# Or using npm
npm install -g @railway/cli

# Login
railway login

# Verify
railway whoami

2. Initialize Project#

# Create new project
railway init

# Or link existing
railway link

3. Add Database#

# Add PostgreSQL
railway add postgresql

# Add Redis
railway add redis

Environment Variables#

Required Variables#

Set these in Railway dashboard (Settings β†’ Variables):

# Database (auto-populated by Railway)
DATABASE_URL=postgresql://...  # Auto-configured

# Only set this if your Railway PostgreSQL endpoint rejects SSL upgrade attempts
# DATABASE_SSL_MODE=disable

# JWT
JWT_SECRET=your-secure-jwt-secret-min-32-chars

# Optional startup behavior
DATABASE_REQUIRED_ON_STARTUP=false

# Site URLs
NEXT_PUBLIC_SITE_URL=https://your-app.railway.app

# Frontend -> API routing
# For a single Railway service, NEXT_PUBLIC_API_URL can stay public.
# For split frontend/backend Railway services, prefer the backend private domain here.
INTERNAL_API_URL=http://your-backend.railway.internal:8080

# Optional public API URL if you intentionally expose the backend directly.
NEXT_PUBLIC_API_URL=https://api.yourdomain.com

# Email (optional)
RESEND_API_KEY=re_your_resend_api_key

Railway JSON Config#

The API service uses a Dockerfile-based deployment and a liveness health check:

{
  "$schema": "https://railway.app/railway.schema.json",
  "build": {
    "builder": "DOCKERFILE",
    "dockerfilePath": "infrastructure/docker/Dockerfile.backend"
  },
  "deploy": {
    "numReplicas": 1,
    "restartPolicyType": "ON_FAILURE",
    "restartPolicyMaxRetries": 10,
    "healthcheckPath": "/health",
    "healthcheckTimeout": 60
  }
}

/health is a liveness endpoint and returns 200 even while the app is still retrying database startup. Use /ready to confirm the database is connected before sending traffic that depends on PostgreSQL.

Database Setup#

1. Create Database#

In Railway dashboard:

  1. Go to your project
  2. Click "New" β†’ "Database" β†’ "PostgreSQL"
  3. Note the connection string

2. Initialize the Schema#

# The API currently bootstraps its tables on startup.
# You can still run ad hoc database commands with Railway CLI if needed.

3. Seed Data (Optional)#

railway run python -m src.api.seed

Deploy#

1. Deploy to Railway#

# Deploy the linked service
railway up

# Or with environment
railway up --environment production

2. View Deployment#

# Open in browser
railway open

# View logs
railway logs

# Follow logs
railway logs -f

3. Verify Deployment#

# Get deployment URL
railway url

# Test health endpoint
curl https://your-app.railway.app/health

Custom Domain#

1. Add Domain#

In Railway dashboard:

  1. Go to project β†’ Settings β†’ Domains
  2. Add custom domain (e.g., mutx.dev)
  3. Note the CNAME record

2. Configure DNS#

Add CNAME record:

Type: CNAME
Name: mutx.dev
Value: your-app.railway.app

3. SSL#

Railway automatically provisions Let's Encrypt SSL.

Multiple Services#

For a more complete setup, create multiple Railway services:

Service 1: Frontend (Next.js)#

{
  "name": "frontend",
  "build": {
    "builder": "NIXPACKS"
  },
  "deploy": {
    "numReplicas": 2,
    "startCommand": "npm run start"
  }
}

Service 2: API (FastAPI)#

Use the checked-in backend Dockerfile:

infrastructure/docker/Dockerfile.backend

Railway service configs in this repo already point at the canonical backend and frontend Dockerfiles under infrastructure/docker/.

Production Promotion#

MUTX v1.3 treats Railway as the production host for:

  • mutx.dev
  • app.mutx.dev
  • api.mutx.dev

The repo now includes a production-promotion lane for Railway so web/app rollout does not depend on a local operator shell.

GitHub Actions secrets#

Set these repository secrets before using the Railway promotion workflow:

  • RAILWAY_TOKEN
  • RAILWAY_PROJECT_ID
  • RAILWAY_FRONTEND_SERVICE_ID
  • RAILWAY_API_SERVICE_ID
  • RAILWAY_ENVIRONMENT_ID

Optional repository variables or workflow inputs:

  • MUTX_SITE_URL
  • MUTX_APP_URL
  • MUTX_API_URL
  • MUTX_DOCS_RELEASE_URL

Promotion flow#

bash scripts/promote-railway-production.sh
bash scripts/verify-production-release.sh

Live production note#

Live production project: zooming-youth.

Live Railway production currently runs the backend without an explicit healthcheckPath/healthcheckTimeout in the deployed service manifest, even though repo-side examples may show those fields. Do not change backend Railway healthcheck behavior casually from repo config alone.

Live Railway production currently serves these custom domains:

  • frontend custom domains: mutx.dev, app.mutx.dev
  • backend custom domain: api.mutx.dev

Live Railway production also uses this backend preDeployCommand:

python -m pip install -q psycopg2-binary alembic && python -m alembic upgrade head

Treat the backend preDeployCommand as production-critical until Railway and repo config are intentionally reconciled. Use live Railway service manifests as the source of truth before changing production deployment behavior.

The verification step should confirm:

  • https://mutx.dev
  • https://mutx.dev/download/macos
  • https://app.mutx.dev/login
  • https://app.mutx.dev/register
  • https://app.mutx.dev/dashboard
  • https://api.mutx.dev/health
  • https://api.mutx.dev/ready
  • https://docs.mutx.dev/docs/v1.3

Create railway.json for API:

{
  "name": "api",
  "build": {
    "builder": "DOCKERFILE",
    "dockerfilePath": "api/Dockerfile"
  },
  "deploy": {
    "numReplicas": 2,
    "startCommand": "uvicorn src.api.main:app --host 0.0.0.0 --port 8000"
  }
}

Troubleshooting#

Build Failed#

# Check build logs
railway logs --type build

Service Not Starting#

# Check runtime logs
railway logs --type runtime

# Common issues:
# - Missing environment variables
# - Port not exposed
# - Build command incorrect

Database Connection#

# Verify DATABASE_URL
railway variables | grep DATABASE

# Optional: disable SSL if the proxy rejects SSL upgrades
railway variables set DATABASE_SSL_MODE=disable

Custom Domain Not Working#

# Verify DNS propagation
dig yourdomain.com

# Check Railway domain status
railway domain list

Maintenance#

Update Deployment#

# Deploy new version
git push railway main

# Or trigger manually
railway up

Rollback#

In Railway dashboard:

  1. Go to Deployments
  2. Find previous deployment
  3. Click "Redeploy"

Scale#

In Railway dashboard:

  • Go to Settings β†’ Scaling
  • Adjust replicas (max 20 on Pro plan)

Quick Reference#

# Login
railway login

# Initialize
railway init

# Deploy
railway up

# View logs
railway logs

# Add service
railway add postgresql

# Variables
railway variables

# Custom domain
railway domain add yourdomain.com
Previousv0.1 Release RunbookNextTroubleshooting

Last updated via GitBook sync β€” source at GitHub

On this page

Railway Setup1. Install Railway CLI2. Initialize Project3. Add DatabaseEnvironment VariablesRequired VariablesRailway JSON ConfigDatabase Setup1. Create Database2. Initialize the Schema3. Seed Data (Optional)Deploy1. Deploy to Railway2. View Deployment3. Verify DeploymentCustom Domain1. Add Domain2. Configure DNS3. SSLMultiple ServicesService 1: Frontend (Next.js)Service 2: API (FastAPI)Production PromotionGitHub Actions secretsPromotion flowLive production noteTroubleshootingBuild FailedService Not StartingDatabase ConnectionCustom Domain Not WorkingMaintenanceUpdate DeploymentRollbackScaleQuick Reference