Railway provides a simple platform for deploying containerized applications with built-in PostgreSQL databases. This guide covers deploying AgentDoor with Express to Railway.
Quick Deploy
Deploy the Railway template in one click:
Click Deploy Button
Click the “Deploy on Railway” button above to create a new project from the template.
Configure Environment
Set the X402_WALLET environment variable to your wallet address for receiving micropayments.
Deploy
Railway automatically builds and deploys your application using the included Dockerfile.
Manual Setup
For custom deployments or integration into existing projects:
1. Install Dependencies
npm install express @agentdoor/express
2. Create Express Application
Create src/index.ts with AgentDoor middleware:
import express from 'express' ;
import { agentDoor } from '@agentdoor/express' ;
const app = express ();
const PORT = process . env . PORT || 3000 ;
// Middleware
app . use ( express . json ());
// AgentDoor middleware
app . use (
'/api' ,
agentDoor ({
scopes: [
{ id: 'data.read' , description: 'Read application data' , price: '$0.001/req' },
{ id: 'data.write' , description: 'Write application data' , price: '$0.01/req' },
{ id: 'admin' , description: 'Administrative operations' , price: '$0.05/req' },
],
service: {
name: 'My Agent-Ready API' ,
description: 'Express API with AgentDoor authentication' ,
},
x402: {
network: 'base' ,
currency: 'USDC' ,
paymentAddress: process . env . X402_WALLET || '0xYourWalletAddress' ,
},
})
);
// Routes
app . get ( '/' , ( req , res ) => {
res . json ({
name: 'Agent-Ready Express API' ,
discovery: '/.well-known/agentdoor' ,
});
});
app . get ( '/api/data' , ( req , res ) => {
// This route requires data.read scope
res . json ({
success: true ,
data: [ /* your data */ ]
});
});
app . listen ( PORT , () => {
console . log ( `Server running on port ${ PORT } ` );
});
export default app ;
3. Create Dockerfile
Create a Dockerfile in your project root:
FROM node:20-alpine AS builder
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci
# Copy source and build
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build
# Production image
FROM node:20-alpine
WORKDIR /app
# Install production dependencies only
COPY package*.json ./
RUN npm ci --omit=dev
# Copy compiled output
COPY --from=builder /app/dist ./dist
# Set default port
ENV PORT=3000
EXPOSE 3000
CMD [ "node" , "dist/index.js" ]
Create railway.json in your project root:
{
"$schema" : "https://railway.app/railway.schema.json" ,
"build" : { "builder" : "NIXPACKS" },
"deploy" : { "startCommand" : "npm start" }
}
5. Deploy to Railway
Install Railway CLI
npm install -g @railway/cli
Set Environment Variables
railway variables set X402_WALLET=0xYourWalletAddress
Storage Configuration
Railway supports multiple storage options for AgentDoor:
SQLite (Development)
For single-instance deployments with persistent volumes:
import { SQLiteStore } from '@agentdoor/core/advanced/storage' ;
const store = new SQLiteStore ({
path: './data/agentdoor.db'
});
app . use ( '/api' , agentDoor ({
// ... other config
storage: store
}));
SQLite requires a persistent volume. Configure in Railway dashboard under Settings → Volumes .
PostgreSQL (Production)
Railway provides managed PostgreSQL. Add a database to your project:
Add PostgreSQL
In Railway dashboard, click New → Database → PostgreSQL .
Link Database
Railway automatically sets the DATABASE_URL environment variable.
Configure Storage
import { PostgresStore } from '@agentdoor/core/storage/postgres' ;
const store = new PostgresStore ({
connectionString: process . env . DATABASE_URL
});
app . use ( '/api' , agentDoor ({
// ... other config
storage: store
}));
Environment Variables
Set these variables in the Railway dashboard or via CLI:
Variable Description Required Default X402_WALLETWallet address for receiving x402 payments Yes - PORTServer port No 3000 DATABASE_URLPostgreSQL connection string Conditional - NODE_ENVNode environment No production
Setting Variables via CLI
# Set a single variable
railway variables set X402_WALLET=0xYourAddress
# Set multiple variables
railway variables set \
X402_WALLET=0xYourAddress \
NODE_ENV=production
# View all variables
railway variables
Setting Variables via Dashboard
Open your project in Railway dashboard
Navigate to Variables tab
Click New Variable
Enter variable name and value
Click Add
Custom Domains
Generate Railway Domain
Railway automatically provides a railway.app subdomain. Find it in the Settings tab.
Add Custom Domain
Navigate to Settings → Domains → Custom Domain and enter your domain.
Configure DNS
Add a CNAME record pointing to your Railway deployment: CNAME api.yourdomain.com your-app.railway.app
Enable SSL
Railway automatically provisions SSL certificates via Let’s Encrypt.
Health Checks and Monitoring
Health Check Endpoint
Add a health check endpoint for Railway monitoring:
app . get ( '/health' , ( req , res ) => {
res . json ({
status: 'healthy' ,
uptime: process . uptime (),
timestamp: new Date (). toISOString (),
environment: process . env . NODE_ENV
});
});
Configure in Railway dashboard under Settings → Health Check :
Path : /health
Port : 3000 (or your configured port)
Timeout : 30s
Logging
View logs in Railway dashboard or via CLI:
# Stream logs
railway logs
# View recent logs
railway logs --tail 100
Scaling
Vertical Scaling
Increase resources in Railway dashboard under Settings → Resources :
Memory : 512MB - 32GB
CPU : Shared - 8 vCPUs
Horizontal Scaling
For horizontal scaling, use Railway’s replica feature:
Navigate to Settings → Scaling
Increase Replica Count
Configure load balancing
Horizontal scaling requires PostgreSQL or external storage. SQLite with volumes only works with single instances.
CI/CD Integration
Railway automatically deploys on git push when connected to a repository.
GitHub Integration
Connect Repository
In Railway dashboard, click Settings → Connect Repository .
Configure Branch
Select the branch to deploy (e.g., main or production).
Enable Auto-Deploy
Railway automatically deploys on every push to the selected branch.
Manual Deployments
Deploy manually via CLI:
# Deploy current directory
railway up
# Deploy specific branch
railway up --branch production
Troubleshooting
Build Failures
If builds fail, check:
Dependencies : Ensure all dependencies are in package.json
Build script : Verify build script in package.json
TypeScript : Check tsconfig.json configuration
# Test build locally
npm run build
Database Connection Issues
If database connections fail:
Verify DATABASE_URL is set correctly
Check PostgreSQL service is running
Review connection string format:
postgresql://user:password@host:port/database
Port Binding
Ensure your app listens on the PORT environment variable:
const PORT = process . env . PORT || 3000 ;
app . listen ( PORT );
Best Practices
Use PostgreSQL for Production : SQLite is suitable for development, but PostgreSQL is recommended for production.
Enable Health Checks : Configure health checks to monitor application availability.
Set NODE_ENV : Always set NODE_ENV=production for production deployments.
Use Secrets for Sensitive Data : Store sensitive values like API keys and wallet addresses as environment variables, never in code.
Monitor Logs : Regularly review logs for errors and performance issues.
Backup Database : Enable automated backups for PostgreSQL in Railway dashboard.
Next Steps
Configure Storage Learn about storage options and configuration
Rate Limiting Configure rate limits for agents
Webhooks Set up webhooks for agent events
Monitoring Monitor your AgentDoor deployment