Self-Hosting
Deploy Bulwark on your own infrastructure using Docker or Railway.
Prerequisites
- Docker + Docker Compose (for local/VPS deployment)
- PostgreSQL 15+
- Valkey 7+ (or Redis 7+)
- A domain with TLS (for production)
Docker Compose
1. Clone the repository
git clone https://github.com/bulwarkauth/bulwark
cd bulwark
2. Configure environment
cp .env.example .env
Edit .env:
# Database
DATABASE_URL=postgres://bulwark:password@postgres:5432/bulwark?sslmode=disable
# Valkey/Redis
VALKEY_URL=redis://valkey:6379
# JWT
JWT_SECRET=change-me-use-a-long-random-string
JWT_EXPIRY=15m
REFRESH_TOKEN_EXPIRY=7d
# Encryption (32 bytes hex)
ENCRYPTION_KEY=your-32-byte-hex-key-here
# Server
PORT=8080
ENV=production
# Admin
ADMIN_EMAIL=admin@yourdomain.com
ADMIN_PASSWORD=change-me
3. Start services
docker compose up -d
Services started:
bulwark-apion port 8080postgreson port 5432 (internal)valkeyon port 6379 (internal)bulwark-adminon port 3100bulwark-landingon port 3200
4. Run migrations
docker compose exec bulwark-api ./bulwark migrate up
5. Verify
curl http://localhost:8080/health
# {"status":"ok","version":"0.1.0"}
Railway Deployment
One-click deploy
Manual Railway setup
# Install Railway CLI
npm install -g @railway/cli
# Login and link
railway login
railway link
# Set environment variables
railway variables set JWT_SECRET=$(openssl rand -hex 32)
railway variables set ENCRYPTION_KEY=$(openssl rand -hex 32)
# Deploy
railway up
Railway auto-provisions PostgreSQL and Redis. Set DATABASE_URL and REDIS_URL from the Railway dashboard.
Environment Variables Reference
| Variable | Required | Description |
|----------|----------|-------------|
| DATABASE_URL | Yes | PostgreSQL connection string |
| VALKEY_URL | Yes | Valkey/Redis connection string |
| JWT_SECRET | Yes | Secret for JWT signing (min 32 chars) |
| ENCRYPTION_KEY | Yes | AES-256 key for vault encryption (32 bytes hex) |
| PORT | No | API server port (default: 8080) |
| ENV | No | development or production |
| LOG_LEVEL | No | debug, info, warn, error |
| ADMIN_EMAIL | No | Bootstrap admin account email |
| ADMIN_PASSWORD | No | Bootstrap admin account password |
Reverse Proxy (Nginx)
server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /etc/ssl/certs/yourdomain.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.key;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Health Checks
# API health
GET /health
# Database connectivity
GET /health/db
# Cache connectivity
GET /health/cache