Self-Hosted VPS Deployment
Deploy your ChainPay backend to a single VPS (Virtual Private Server) using Docker Compose and Caddy. Frontends are served statically via Vercel for maximum reliability and global edge delivery.
1. The Container Stack
The production stack runs in a isolated virtual network. The reverse proxy container exposes ports 80 and 443 to handle HTTPS routing and SSL certificates automatically:
version: '3.8'
services:
# Database
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: chainpay
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: chainpay
volumes:
- postgres_prod_data:/var/lib/postgresql/data
restart: always
# Redis Queue Cache
redis:
image: redis:alpine
restart: always
# Inngest Server
inngest:
image: inngest/inngest:latest
command: >
inngest start --host 0.0.0.0 --port 8288
--postgres-uri postgresql://chainpay:${DB_PASSWORD}@postgres:5432/chainpay?sslmode=disable
--redis-uri redis://redis:6379/0
environment:
- INNGEST_EVENT_KEY=${INNGEST_EVENT_KEY}
- INNGEST_SIGNING_KEY=${INNGEST_SIGNING_KEY}
restart: always
# Express REST API
api:
image: ${API_IMAGE:-chainpay-api-prod}
environment:
- DATABASE_URL=postgres://chainpay:${DB_PASSWORD}@postgres:5432/chainpay
- INNGEST_BASE_URL=http://inngest:8288
- INNGEST_EVENT_KEY=${INNGEST_EVENT_KEY}
- INNGEST_SIGNING_KEY=${INNGEST_SIGNING_KEY}
command: sh -c "pnpm --filter api db:push && pnpm --filter api run start"
restart: always
# Caddy reverse proxy for SSL
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
restart: always2. Setting up Credentials & Starting
Use our built-in script to generate database passwords, secure API keys, and Caddy password hashes:
# Run the setup script to generate secure keys and basic-auth credentials
node scripts/generate-env.js
# Edit `.env.production` to insert your domains and RPC base urls:
# API_DOMAIN=api.nodecheckout.com
# INNGEST_DOMAIN=inngest.nodecheckout.com
# RPC_BASE_URL=https://base-sepolia.g.alchemy.com/v2/YOUR_ALCHEMY_KEY
# Spin up all containerized backend services
docker compose -f docker-compose.prod.yml up -d --buildBy default, the self-hosted Inngest Dashboard exposes event telemetry, function logs, and payment states without authentication. We place it behind Caddy's basic authentication. You must configure the hashed password generated by the script inside your VPS environments.
3. Syncing Inngest Functions
Once the VPS container stack is running:
- Access your secure dashboard at
https://inngest.nodecheckout.com. - Login using username
adminand your generated dashboard cleartext password. - In the "Apps" configuration page, trigger a sync by entering your Express API SDK endpoint:
http://api:4000/api/inngest. - Inngest will scan the endpoints and register your payment workflows.