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-api on port 8080
  • postgres on port 5432 (internal)
  • valkey on port 6379 (internal)
  • bulwark-admin on port 3100
  • bulwark-landing on 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

Deploy on Railway

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