Steps
- Fork this repo (so Railway can hook into your GitHub).
- Go to railway.app/new → Deploy from GitHub repo → pick the fork.
- Railway auto-detects the Next.js app and starts a build. Cancel the first build — we need to add Postgres and env vars first.
- In the project, click + New → Database → Add PostgreSQL. Railway provisions it and exposes
DATABASE_URLas a service variable. - On the mantis service, Variables → add:
DATABASE_URL→ use the Reference syntax to link to the Postgres service:${{ Postgres.DATABASE_URL }}PUBLIC_BASE_URL→ leave blank for now; you’ll fill it in after step 7MANTIS_API_KEY_PEPPER→ generate withopenssl rand -base64 32. Required. Do not rotate after the first key is minted — it invalidates every existing API key.AUTO_MIGRATE→1BOOTSTRAP_API_KEY→ generate one withnode -e "console.log('mantis_live_' + require('crypto').randomBytes(24).toString('base64url'))"and save it locally — you’ll need it to log into the dashboard- (Optional)
SMTP_URL,SMTP_FROMfor email notifications
- On the mantis service, Settings → Networking → Generate Domain. Railway gives you a
<name>.up.railway.appURL. - Set
PUBLIC_BASE_URLto that URL (e.g.,https://mantis.up.railway.app) and redeploy. - Before broad public use, decide whether to keep the Railway domain directly exposed or put a Cloudflare-proxied custom domain in front for WAF/rate limiting. See public edge limits.
- Visit
https://<your-domain>/login, paste theBOOTSTRAP_API_KEYyou generated. Done.
Public edge limits
Railway’s edge currently enforces useful platform limits, including a 32 KB combined request-header limit and network-level DDoS mitigation, but Railway does not provide an application-layer WAF. For public Mantis trigger URLs, the recommended production posture is:- Add a custom domain to the Mantis Railway service.
- Put that hostname behind Cloudflare’s orange-cloud proxy.
- Configure the
/c/*,/status/*, and optional/api/wallet/*rules in public edge limits. - Set
TRUST_PROXY_HEADERS=1only when Cloudflare is the public entry point and no direct Railway hostname is advertised.
Notes
- Railway no longer has a true free tier; expect ~$5/month for the smallest combined plan (mantis service + Postgres).
- The notify worker runs natively (no cron config needed —
instrumentation.tsauto-detects non-Vercel and starts it). - Auto-deploys on push to the connected branch.
- To use an external Postgres (Neon, Supabase) instead of Railway Postgres: drop the linked DB and set
DATABASE_URLto an external connection string.
Redis/Valkey for rate limiting?
Not by default. A shared Redis/Valkey limiter is useful only if you run multiple Mantis replicas or need strict shared counters. For a single Railway Mantis service, start with Cloudflare/proxy limits plus the built-in duplicate suppression. Railway Redis is deployed as another service. Using Railway’s current resource pricing, a tiny 256 MB Redis/Valkey service is about 5/month minimum counts toward usage, so it may fit inside the minimum if the rest of the project is small. It does add another private-network round trip to each/c/* hit and another service to operate.