Deploy to Railway
Step-by-step guide to deploying Edictum Console on Railway. Three services, one deploy, under ten minutes.
Right page if: you want to deploy Edictum Console on Railway with Postgres and Redis plugins. Wrong page if: you want to self-host with Docker Compose on your own infrastructure (see https://docs.edictum.ai/docs/console/self-hosting). Gotcha: you do not need to set DATABASE_URL or REDIS_URL manually -- Railway auto-injects them and the docker-entrypoint.sh maps them to the EDICTUM_ prefixed format.
Step-by-step guide to deploying Edictum Console on Railway. Three services (Postgres, Redis, console), one deploy, under ten minutes.
Prerequisites
- A Railway account (free tier works for evaluation)
- Your code in a GitHub repo, or the Railway CLI installed
1. Create a Project
Option A: From GitHub (recommended)
- Go to railway.app/new
- Select Deploy from GitHub repo
- Connect your fork of
edictum-console - Railway detects the
Dockerfileandrailway.tomlautomatically
Option B: Railway CLI
cd edictum-console
railway login
railway init
railway link2. Add Postgres
- In your Railway project, click + New > Database > Add PostgreSQL
- Railway creates a Postgres instance and auto-injects
DATABASE_URLinto your service
No configuration needed. The docker-entrypoint.sh automatically maps Railway's DATABASE_URL (which uses postgresql://) to EDICTUM_DATABASE_URL with the postgresql+asyncpg:// driver prefix that the server requires.
3. Add Redis
- Click + New > Database > Add Redis
- Railway creates a Redis instance and auto-injects
REDIS_URLinto your service
Again, the entrypoint maps REDIS_URL to EDICTUM_REDIS_URL automatically if the EDICTUM_ prefixed variant isn't set.
4. Configure Environment Variables
In your console service, go to Variables and add these:
Required
Generate secrets locally and paste them in:
# Run this twice, once for each secret
python -c "import secrets; print(secrets.token_hex(32))"| Variable | Value | Purpose |
|---|---|---|
EDICTUM_SECRET_KEY | 64-char hex from above | Session token signing |
EDICTUM_SIGNING_KEY_SECRET | 64-char hex from above | Ed25519 key encryption for bundle signing |
First-run Bootstrap
Set these to auto-create the admin account on first startup:
| Variable | Value | Purpose |
|---|---|---|
EDICTUM_ADMIN_EMAIL | Your email | Bootstrap admin user |
EDICTUM_ADMIN_PASSWORD | Strong password (min 12 chars) | Bootstrap admin password |
Alternatively, skip these and use the setup wizard at https://<your-domain>/dashboard/setup after the first deploy.
Recommended for Production
| Variable | Value | Purpose |
|---|---|---|
EDICTUM_BASE_URL | https://your-domain.up.railway.app | Public URL (enables secure cookies, CORS, notification callbacks) |
EDICTUM_CORS_ORIGINS | Same as EDICTUM_BASE_URL | Allowed CORS origins |
EDICTUM_TRUSTED_PROXIES | * | Required on Railway — Railway injects a proxy with a dynamic IP. Without this, the server logs a startup warning and rate limiting keys on the proxy IP rather than the real client IP. |
EDICTUM_AUTH_PROVIDER | local | Auth provider (only option currently) |
EDICTUM_ENV_NAME | production | Disables OpenAPI docs, sets env label |
EDICTUM_SESSION_TTL_HOURS | 24 | Session cookie lifetime |
What You Don't Need to Set
Railway auto-injects DATABASE_URL and REDIS_URL from the plugin services. The entrypoint handles the mapping. You only need to set EDICTUM_DATABASE_URL / EDICTUM_REDIS_URL manually if you're using external databases.
5. Deploy
If you connected a GitHub repo, Railway deploys automatically on push. For CLI:
railway upRailway reads railway.toml which configures:
- Builder: Dockerfile (multi-stage: frontend build, Python build, slim runtime)
- Health check:
GET /api/v1/healthwith 60s timeout - Restart policy: On failure, max 3 retries
First deploy takes 3-5 minutes (Docker build + dependency install). Subsequent deploys are faster due to layer caching.
6. Custom Domain (Optional)
- In your service settings, go to Networking > Custom Domain
- Add your domain (e.g.,
console.example.com) - Add the CNAME record Railway provides to your DNS
- Railway handles TLS automatically
- Update
EDICTUM_BASE_URLandEDICTUM_CORS_ORIGINSto match the custom domain
Railway also provides an auto-generated domain like edictum-console-production-xxxx.up.railway.app which works immediately.
7. Verify
Check the health endpoint:
curl https://<your-domain>/api/v1/healthExpected response:
{
"status": "ok",
"bootstrap_complete": true
}Then open https://<your-domain>/dashboard to log in.
Troubleshooting
Build fails
Check the build logs in Railway's dashboard. Common causes:
- Out of memory during frontend build -- Railway's free tier has limited build resources. Upgrade the plan or push a pre-built image instead.
- pnpm lockfile mismatch -- ensure
dashboard/pnpm-lock.yamlis committed and up to date.
Server starts but health check fails
The health check hits /api/v1/health with a 60s timeout. If the server takes too long:
- Check deploy logs for migration errors (
alembic upgrade headruns on startup) - Ensure Postgres and Redis plugins are running (check their service status in Railway)
- Verify the internal connection URLs are correct -- Railway uses
*.railway.internalhostnames between services
Database connection refused
Railway's Postgres is on the internal network at postgres.railway.internal:5432. If you manually set EDICTUM_DATABASE_URL, ensure you're using the internal hostname, not the public proxy URL, for lower latency.
Session cookies not persisting
Set EDICTUM_BASE_URL to your actual public URL with https://. Without this, the server won't set the Secure flag on cookies, and browsers may reject them over HTTPS.
Notification buttons don't work
Interactive notification buttons (Telegram approve/deny) require EDICTUM_BASE_URL to be a public HTTPS URL so the callback URLs resolve correctly.
Migrations
Alembic migrations run automatically on every deploy via docker-entrypoint.sh. No manual migration steps needed. Check deploy logs if you suspect a migration failure.
Cost Estimate
Railway's pricing is usage-based. A typical Edictum Console deployment uses:
- Console service: ~256MB RAM idle, spikes during builds
- Postgres: ~100MB RAM
- Redis: ~50MB RAM
This fits comfortably within Railway's Hobby plan. Check Railway pricing for current rates.
Last updated on