Railway Deployment
Golems Phase 2 runs on Railway as the cloud "body" while the Mac remains the "brain" (Telegram bot, Night Shift, notifications).
Railway Project
Create a new project in Railway with these settings:
- Organization: Your Railway org
- Project: golems (or any name you choose)
- Service: golems
- Region: Any region (US West, Europe, etc.)
- Root:
/(repo root) - Builder: Dockerfile
Getting Started
Install Railway CLI
brew install railwayAuthenticate
railway login
# Opens browser to authorizeLink Project
From repo root:
railway link
# Select your org
# Select your projectDeploy
railway up
# Rebuilds Docker image and deploysWatch logs:
railway logs -fEnvironment Variables
Set all 18 variables in Railway dashboard (Settings → Variables):
Core Configuration
| Variable | Value | Notes |
|---|---|---|
LLM_BACKEND | gemini | Cloud execution (free Gemini Flash-Lite) |
STATE_BACKEND | supabase | Cloud state |
TELEGRAM_MODE | direct | Direct API calls |
TZ | Asia/Jerusalem | Scheduling |
API Keys (from 1Password)
| Variable | Source | Required |
|---|---|---|
GOOGLE_GENERATIVE_AI_API_KEY | Google AI Studio | ✅ Yes |
SUPABASE_URL | Your Supabase project (format: https://YOUR_PROJECT.supabase.co) | ✅ Yes |
SUPABASE_SERVICE_KEY | Supabase dashboard → Settings → API | ✅ Yes |
GMAIL_CLIENT_ID | Google Cloud Console → OAuth credentials | ✅ Yes |
GMAIL_CLIENT_SECRET | Google Cloud Console | ✅ Yes |
GMAIL_REFRESH_TOKEN | OAuth flow (see Gmail setup docs) | ✅ Yes |
TELEGRAM_BOT_TOKEN | @BotFather on Telegram | ✅ Yes |
TELEGRAM_CHAT_ID | Your Telegram group/chat ID | ✅ Yes |
Telegram Topics
Two topics in the Telegram group:
| Variable | Purpose |
|---|---|
TELEGRAM_TOPIC_GENERAL | Interactive ClaudeGolem chat |
TELEGRAM_TOPIC_ALERTS | One-way notifications (jobs, email, nightshift, health) |
Monitoring
| Variable | Value | Purpose |
|---|---|---|
RAILWAY_URL | Auto-populated by Railway | Health check endpoint |
Health & Monitoring
Health Check Endpoint
GET /health
Returns 200 OK with:
{
"status": "ok",
"uptime": 3600,
"backend": "gemini",
"stateBackend": "supabase",
"telegramMode": "direct",
"israelTime": "2026-02-06T12:30:00+02:00",
"isWorkHours": true,
"isWorkday": true
}Railway automatically checks /health every 30 seconds.
Usage Metrics Endpoint
GET /usage
Returns API cost stats:
{
"totalCalls": 145,
"totalInputTokens": 28450,
"totalOutputTokens": 12890,
"estimatedCostUSD": 0.58,
"recentCalls": [
{
"timestamp": "2026-02-06T10:30:00Z",
"model": "gemini-2.5-flash-lite",
"source": "email-golem",
"inputTokens": 1250,
"outputTokens": 342
}
],
"bySource": {
"email-golem": { "calls": 52, "cost": 0.23 },
"job-golem": { "calls": 93, "cost": 0.35 }
}
}Uptime Monitoring
Configure UptimeRobot (free tier):
- Go to uptimerobot.com
- Add monitor:
https://your-service.up.railway.app/health - Check every 5 minutes
- Set webhook notification to Telegram (optional - configure bot webhook)
- Receives alerts in Telegram
⏰ Uptimetopic
Rollback Strategy
All configs are environment-based for quick rollback:
Revert LLM Backend
If cloud LLM has issues:
railway variables set LLM_BACKEND=ollama
railway upThen switch back:
railway variables set LLM_BACKEND=gemini
railway upRevert State Backend
If Supabase has issues:
railway variables set STATE_BACKEND=file
railway upRevert Telegram Mode
If direct notifications fail:
railway variables set TELEGRAM_MODE=local
railway upDatabase Migrations
Supabase migrations are managed via the Supabase MCP or dashboard:
# List pending migrations
supabase migration list --linked
# Apply migration
supabase db pushPhase 2 migration: 003_cloud_offload.sql
Logs & Debugging
View Logs
# Stream live logs
railway logs -f
# Last 100 lines
railway logsCommon Issues
502 Bad Gateway
- Check if service is running:
railway logs -f - Verify all required env vars are set
- Check SUPABASE_URL and SUPABASE_SERVICE_KEY
Telegram notifications not sending
- Verify TELEGRAM_BOT_TOKEN is correct
- Check TELEGRAM_CHAT_ID is negative (for groups)
- Verify topic IDs (TELEGRAM_TOPIC_*)
LLM calls failing
- Check GOOGLE_GENERATIVE_AI_API_KEY is set
- Verify API key is valid in Google AI Studio
- Check logs for rate limiting
Debug Command
railway exec bash
# Now in Railway container
bun run src/cloud-worker.tsCost Management
Monitor API costs in three places:
- Railway dashboard — Compute (usually $5-10/month)
- Google AI Studio — LLM calls (Gemini Flash-Lite is free tier)
- Supabase dashboard — Database queries
Gemini Flash-Lite is free for personal use. Total monthly cost is mostly Railway compute: ~$5-10.
Scaling
Horizontal
Railway auto-scales based on CPU/memory:
# Check current plan
railway environments list
# Upgrade to Pro for auto-scaling
# (requires paid Railway account)Vertical
Increase memory in railway.json:
{
"services": {
"golems": {
"runtime": "dockerfile",
"memory": "512",
"cpus": "1"
}
}
}See Also
- Environment Variables — Complete variable reference
- Secrets Management — How to store API keys
- Golems Architecture — System design