Railway Platform
Railway gives Git-triggered builds, IPv6 private networking, and automatic TLS for public services. LeafLock’s frontend runs publicly while the backend stays private.
Railway Platform
Railway gives Git-triggered builds, IPv6 private networking, and automatic TLS for public services. LeafLock’s frontend runs publicly while the backend stays private.
Services created inside one Railway project:
leaflock-backend (private service, no domain)leaflock-frontend (public domain)Set strong values before first deploy. Railway injects them at build and runtime.
openssl rand -base64 64 # JWT_SECRETopenssl rand -base64 32 # SERVER_ENCRYPTION_KEYopenssl rand -base64 32 # DEFAULT_ADMIN_PASSWORD
# Railway UI → Backend → VariablesJWT_SECRET=<value>SERVER_ENCRYPTION_KEY=<value>DEFAULT_ADMIN_EMAIL=ops@yourdomain.comDEFAULT_ADMIN_PASSWORD=<value>ENABLE_REGISTRATION=false/backendDATABASE_URL=$RAILWAY_POSTGRES_URLPOSTGRES_PASSWORD=$RAILWAY_POSTGRES_PASSWORDREDIS_URL=$RAILWAY_REDIS_URLREDIS_PASSWORD=$RAILWAY_REDIS_PASSWORDJWT_SECRET=<from secrets>SERVER_ENCRYPTION_KEY=<from secrets>APP_ENV=productionCORS_ORIGINS=https://leaflock-frontend-production.up.railway.appENABLE_METRICS=trueENABLE_DEFAULT_ADMIN=trueThe Go server binds to [::]:8080 (backend/server/listener.go) so Railway IPv6 networking works out of the box.
/frontend80leaflock-frontend-production.up.railway.app)BACKEND_INTERNAL_URL=http://leaflock-backend.railway.internal:8080VITE_API_URL=/api/v1PORT=80NODE_ENV=productionVITE_ENABLE_ADMIN_PANEL=falseVITE_FEATURE_SHARE_LINKS=trueCaddy (frontend/docker-entrypoint.sh) resolves the .railway.internal hostname on every request, preventing stale IPv6 records.
railway initrailway link
# Deploy backend first (runs migrations, seeds admin/templates)railway up --service leaflock-backend
# Watch logs until "HTTP server starting on [::]:8080"
# Then deploy frontendrailway up --service leaflock-frontendVerify health via the public domain:
curl https://leaflock-frontend-production.up.railway.app/healthcurl https://leaflock-frontend-production.up.railway.app/api/v1/health/readyCommit a railway.json (optional) to codify services:
{"$schema": "https://railway.app/config.v2024.05.31.schema.json","project": { "name": "leaflock", "services": [ { "name": "leaflock-backend", "path": "./backend", "plugins": [{ "name": "postgres" }, { "name": "redis" }], "variables": { "APP_ENV": "production", "ENABLE_METRICS": "true" } }, { "name": "leaflock-frontend", "path": "./frontend", "variables": { "VITE_API_URL": "/api/v1", "BACKEND_INTERNAL_URL": "http://leaflock-backend.railway.internal:8080", "PORT": "80" } } ]}}Railway applies plugin variables automatically; only set secrets that are not provided by the plugins.
CNAME to the Railway hostname.CORS_ORIGINS to include the new domain.ENABLE_REGISTRATION based on whether sign-ups should be public.BACKEND_INTERNAL_URL points to leaflock-backend.railway.internal:8080.FATAL messages from config.LoadConfig.status=ready.railway logs leaflock-backend)/metrics if enabled