Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vane.build/llms.txt

Use this file to discover all available pages before exploring further.

Prerequisites

  • A Railway account
  • The Railway CLI installed
  • Your Vane repository on GitHub (or deploy directly from the CLI)

Step 1: Create a new Railway project

railway login
railway init
# Select "Empty Project"

Step 2: Add a PostgreSQL database

From the Railway dashboard: New Service → Database → PostgreSQL. Railway provisions the database and sets DATABASE_URL in the same project environment automatically. Or via CLI:
railway add --plugin postgresql

Step 3: Set environment variables

Required:
railway variables set COUNSEL_MASTER_KEY=$(openssl rand -hex 32)
Optional but recommended:
railway variables set LOG_LEVEL=info
railway variables set SPIFFE_TRUST_DOMAIN=vane.build
railway variables set COUNSEL_BASE_URL=https://$(railway domain)
If you have a Sentry project:
railway variables set SENTRY_DSN=https://key@o1234.ingest.sentry.io/5678

Step 4: Deploy

From your local Vane repository:
railway up
Railway detects the package.json start script and runs node dist/api/server.js. You need to run the TypeScript build first:
npm run build
railway up
Or configure Railway to build and start: In railway.toml (create at repo root):
[build]
builder = "NIXPACKS"
buildCommand = "npm ci && npm run build"

[deploy]
startCommand = "npm start"
healthcheckPath = "/v1/health"
healthcheckTimeout = 10

Step 5: Verify

RAILWAY_URL=$(railway domain)

# Health check
curl https://$RAILWAY_URL/v1/health
# { "status": "ok" }

# Register your first company
curl -s -X POST https://$RAILWAY_URL/v1/companies \
  -H "Content-Type: application/json" \
  -d '{ "companyId": "acme" }' | jq .

Environment variable reference

Railway sets DATABASE_URL automatically when a PostgreSQL plugin is added. All other variables must be set manually.
VariableSourceNotes
DATABASE_URLRailway (automatic)Set when PostgreSQL plugin is added.
PORTRailway (automatic)Railway injects PORT automatically — do not set this manually.
COUNSEL_MASTER_KEYYouGenerate with openssl rand -hex 32.
COUNSEL_BASE_URLYouSet to your Railway domain, e.g., https://my-vane.up.railway.app.
SPIFFE_TRUST_DOMAINYouOptional. Defaults to vane.local.
LOG_LEVELYouOptional. Defaults to info.
SENTRY_DSNYouOptional.

Custom domains

In the Railway dashboard: Settings → Domains → Add Domain. After adding your custom domain, update COUNSEL_BASE_URL:
railway variables set COUNSEL_BASE_URL=https://vane.yourdomain.com

Scaling

Railway scales horizontally. If you run multiple replicas, note that:
  • Rate limiting is per-process (in-memory). With multiple replicas, the effective limit is N × per-process limit. Add a shared rate limiter (Redis + ioredis-rate-limiter) for cluster-wide limits.
  • The in-memory attestation chain per tenant is fully loaded on each replica startup. This is fine for development but becomes expensive at scale — each replica holds the full chain in memory.
  • DATABASE_URL is shared across replicas. PostgreSQL handles concurrent writes correctly.