XPayLabs Deployment Guide: Run Your Own Multi-Chain Crypto Payment Gateway
XPayLabs is a production-ready, self-hosted cryptocurrency payment gateway with multi-chain support and multi-tenant architecture. This guide walks through deploying the complete stack — from prerequisites to production go-live.
What You're Deploying
XPayLabs consists of 11 services running in Docker containers:
| Service | Role | Technology |
|---|---|---|
mysql |
Persistent database | MySQL 8.0 |
redis |
Cache, queue, nonce store | Redis 7 Alpine |
sui-node-service |
SUI blockchain RPC proxy | Express (Node.js) |
xpay-tron |
TRON blockchain scanner | Spring Boot 3.4 (Java 17) |
xpay-sui |
SUI blockchain scanner | Spring Boot 3.4 (Java 17) |
xpay-eth |
EVM scanner (ETH, BSC, Polygon, Avalanche) | Spring Boot 3.4 (Java 17) |
xpay-user |
User & collection order API | Spring Boot 3.4 (Java 17) |
xpay-merchant |
Merchant backend API | Spring Boot 3.4 (Java 17) |
merchant-vue |
Merchant admin dashboard | Vue 3 + Element Plus (Nginx) |
checkout |
Payment checkout page | Vue 3 + Vite 7 (Nginx) |
gateway |
Reverse proxy (single entry point) | Nginx Alpine |
All Java services use the same base image (ghcr.io/yan253319066/xpay-java) — different JARs are launched via the command directive.
Prerequisites
- Docker 24+ and Docker Compose v2+
- A Linux server (4 GB RAM minimum, 8 GB recommended)
- Domain names for the merchant dashboard and checkout page
- SSL certificate (Let's Encrypt or commercial)
- RPC endpoints for each blockchain you intend to support
Step 1: Clone the Deployment Repository
git clone https://github.com/yan253319066/XPayLabs-docker.git
cd XPayLabs-docker
This repository contains everything needed for deployment: docker-compose.yml, nginx configs, SQL init scripts, and the .env template.
Step 2: Configure Environment Variables
cp .env.example .env
Edit .env with your own values. Here's what each section means:
Database & Cache
MYSQL_ROOT_PASSWORD=<strong-random-password>
DB_USERNAME=root
DB_PASSWORD=<same-or-different-password>
REDIS_PASSWORD=<optional-redis-password>
MySQL is initialized automatically on first startup — the ./sql/init.sql script is mounted to the container's init directory. Redis password is optional; leave empty for no auth.
Encryption Keys (Critical)
ENCRYPTION_KEY=<exactly-32-characters>
JWT_SECRET_KEY=<random-string>
SKIP_SIGN_SECRET=<64-char-hex-secret>
-
ENCRYPTION_KEY: AES-256-CBC key, must be exactly 32 characters. Used bysui-node-serviceandxpay-suifor encrypting SUI private keys at rest. -
JWT_SECRET_KEY: Used byxpay-merchantfor signing JWT tokens for merchant dashboard sessions. -
SKIP_SIGN_SECRET: HMAC-SHA256 secret used by the SkipSign feature for internal request signing between services.
Public Domains
XPAY_PAY_DOMAIN=https://pay.your-domain.com/checkout
XPAY_API_DOMAIN=https://api.your-domain.com
These are used by the Java services to construct callback URLs and checkout redirects. They must be publicly accessible URLs after you configure DNS.
Blockchain RPC Configuration
EVM chains (ETH, BSC, Polygon, Avalanche):
ETH_NETWORKS=ETH,ETH_SEPOLIA,BSC,BSC_TEST,POLYGON,POLYGON_AMOY,AVAX_C_CHAIN,AVAX_FUJI_TEST
RPC_ETH=https://0xrpc.io/eth,https://rpc.flashbots.net
SCAN_ETH=15
-
ETH_NETWORKS: Comma-separated list of active networks -
RPC_*: Comma-separated RPC URLs (the scanner tries each in order for fault tolerance) -
SCAN_*: Polling interval in seconds between block scans
You can use public RPC endpoints for testnets. For mainnet, consider:
- Commercial RPC providers (Alchemy, Infura, QuickNode) for reliability
- Running your own node for maximum sovereignty
TRON:
TRON_NETWORKS=TRON,TRON_TEST
NODE_TRON=grpc.trongrid.io:50051
SOLIDITY_TRON=grpc.trongrid.io:50052
APIKEY_TRON=<your-trongrid-api-key>
TRON uses gRPC (not JSON-RPC). The scanner connects to a full node and a solidity node. An API key from trongrid.io is required for production use.
SUI:
SUI does not require direct RPC configuration in .env. The xpay-sui scanner communicates with sui-node-service (an Express-based RPC proxy running in the same Docker network) via http://sui-node-service:3001.
Port Mappings
HOST_PORT_GATEWAY_HTTP=180
HOST_PORT_MYSQL=13306
HOST_PORT_REDIS=16379
HOST_PORT_XPAY_USER=18077
HOST_PORT_XPAY_MERCHANT=18078
HOST_PORT_XPAY_ETH=18076
HOST_PORT_XPAY_TRON=18075
HOST_PORT_XPAY_SUI=18074
HOST_PORT_SUI_NODE=13001
Only port 180 (the Nginx gateway) needs to be exposed to the internet. The other ports are for internal communication and optional direct access.
Step 3: Launch the Stack
docker compose up -d
Docker Compose starts services in dependency order:
-
mysqlandredisstart first - Blockchain scanners (
xpay-tron,xpay-eth,xpay-sui+sui-node-service) start after MySQL is healthy -
xpay-userstarts after scanners -
xpay-merchantstarts afterxpay-user - Frontend services (
merchant-vue,checkout) start after their backends -
gateway(Nginx) starts last
Verify the Deployment
# Check all services are running
docker compose ps
# Check logs for each service
docker compose logs xpay-user
docker compose logs xpay-eth
# Test the API
curl http://localhost:180/api/symbol/supportSymbols
Step 4: Configure DNS and SSL
DNS Records
Point your domains to the server's public IP:
merchant.your-domain.com A <server-ip>
pay.your-domain.com A <server-ip>
api.your-domain.com A <server-ip>
The Nginx gateway routes traffic based on path prefixes:
-
/checkout/*→ checkout service (payment page) -
/api/*→ xpay-user API -
/prod-api/*→ xpay-merchant API -
/*→ merchant-vue dashboard (default)
SSL with Let's Encrypt
- Obtain certificates:
docker run -it --rm -p 80:80 -v "$(pwd)/certs:/etc/letsencrypt" certbot/certbot certonly --standalone -d merchant.your-domain.com -d pay.your-domain.com
- Copy the certificates:
cp certs/live/merchant.your-domain.com/fullchain.pem certs/merchant.crt
cp certs/live/merchant.your-domain.com/privkey.pem certs/merchant.key
- Enable SSL in
docker-compose.yml:
gateway:
ports:
- "180:80"
- "1443:443" # uncomment this
volumes:
- ./nginx/gateway.conf:/etc/nginx/conf.d/default.conf
# Replace with:
# - ./nginx/gateway-ssl.conf:/etc/nginx/conf.d/default.conf
- ./certs:/etc/nginx/certs # uncomment this
Update
HOST_PORT_GATEWAY_HTTPS=1443in.envRestart the gateway:
docker compose restart gateway
Step 5: Create the First Merchant
Access the merchant dashboard at http://localhost:180 (or your domain). The registration flow:
- Register — Create a merchant account with email and password
- API Credentials — After login, navigate to Settings → API Keys to generate an API key and secret
- Webhook URL — Configure the callback URL for payment notifications
- Deposit Addresses — The system automatically generates deposit addresses per order using HD wallet derivation — no manual setup needed
Using the API
With your API key and secret:
curl -X POST https://api.your-domain.com/v1/collection/create \
-H "Content-Type: application/json" \
-d '{
"sign": "<hmac-signature>",
"timestamp": 1717000000000,
"nonce": "<uuid>",
"data": {
"amount": "100.00",
"symbol": "USDT",
"chain": "tron",
"orderId": "order_001"
}
}'
SDKs handle signing automatically:
- Node.js:
npm install @xpaylabs/node-sdk - Java: Maven Central
com.xpaylabs:xpay-java-sdk
Architecture Deep Dive
Multi-Tenant Design
XPayLabs is designed as a platform operator model. A single deployment hosts unlimited merchants, each with:
- Isolated data (scoped by
merchant_id) - Separate API credentials (HMAC key pairs)
- Independent webhook configuration
- Configurable fee schedules (you set the rates)
HD Wallet Key Management
The gateway uses BIP-44 hierarchical deterministic wallet derivation:
m / 44' / coin_type' / 0' / 0 / address_index
- Master seed is set via
XPAY_MASTER_SEED(not exposed in this Docker setup — the HD wallet key is embedded in the scanner services) - Database stores only the derivation index, never private keys
- Recovery: restore the seed phrase and replay blockchain history
Blockchain Scanner Architecture
Each blockchain has an independent scanner service that:
- Polls its RPC node at a configurable interval (2-15 seconds)
- Fetches
Transferevents involving tracked deposit addresses - Matches events to pending collection orders
- Updates order status and enqueues webhook delivery
- Waits for chain-specific confirmation count before marking as success
| Chain | Detection Method | Block Time | Recommended Confirmations |
|---|---|---|---|
| TRON | TRON Grid gRPC API | ~3s | 1-2 |
| Ethereum | JSON-RPC eth_getLogs
|
~12s | 12-30 |
| BSC | JSON-RPC polling | ~3s | 15-30 |
| Polygon | JSON-RPC polling | ~2s | 30-100 |
| Avalanche | JSON-RPC polling | ~2s | 10-20 |
| Arbitrum | JSON-RPC polling | ~1s | 10-20 |
| SUI | SUI RPC (via sui-node-service) | ~2s | 5-10 |
Production Operations
Monitoring
- Check service health:
docker compose ps - View logs:
docker compose logs -f --tail=100 <service> - Log files are persisted in
./logs/with per-service subdirectories - Consider adding Uptime Kuma or a similar monitoring tool to watch the gateway endpoint
Database Backups
# Manual backup
docker exec xpay-mysql mysqldump -u root -p xpaylabs > backup_$(date +%Y%m%d).sql
# Automated backup with crontab
0 3 * * * docker exec xpay-mysql mysqldump -u root -p$MYSQL_ROOT_PASSWORD xpaylabs > /backups/xpaylabs_$(date +\%Y\%m\%d).sql
Updating Services
docker compose pull # Pull latest images
docker compose up -d # Restart with new images
The ghcr.io/yan253319066/xpay-java image contains all Java JARs. Update the image tag in docker-compose.yml when a new version is released.
Scaling
The current architecture uses a single-instance deployment. For horizontal scaling:
- Read replicas: Add MySQL read replicas for query-heavy workloads
- Multiple scanners: Run additional scanner instances with different RPC providers for redundancy
- Load balancing: Place multiple gateway instances behind a TCP load balancer
Troubleshooting
"pull access denied" for ghcr.io images
The images are hosted on a public GitHub Container Registry — no authentication required. Common causes:
- Network/firewall blocking ghcr.io — try configuring a Docker proxy or mirror
- ghcr.io rate limiting — wait and retry
If pulling consistently fails, build the images from source:
# Build Java services
cd XPayLabs-java
mvn clean install -P prod -DskipTests
docker build -t ghcr.io/yan253319066/xpay-java .
# Build frontend services
cd XPayLabs-checkout
docker build -t ghcr.io/yan253319066/checkout .
cd XPayLabs-merchant-vue
docker build -t ghcr.io/yan253319066/merchant-vue .
Then update docker-compose.yml to use pull_policy: never and build directives, or tag your local images to match the image names.
MySQL connection refused
MySQL takes ~30-60 seconds to initialize on first run (especially the init SQL). Check health:
docker compose logs mysql
docker compose exec mysql mysqladmin ping -h localhost
Scanner not detecting transactions
- Check the scanner logs for RPC errors
- Verify the RPC endpoint is reachable from the container
- Confirm the deposit address derivation path matches the chain
- Check that
TRON_NETWORKSorETH_NETWORKSincludes the correct network name
Port conflicts
If port 180 is already in use on the host, change HOST_PORT_GATEWAY_HTTP in .env to any available port (e.g., 8080). All internal service ports can also be remapped.
Cost Analysis for Operators
Running XPayLabs as a payment platform operator:
| Item | Monthly Cost |
|---|---|
| Server (4 GB RAM, 2 vCPU) | ~$20-40 |
| RPC endpoints (mainnet) | ~$50-200 (depending on chains) |
| Domain + SSL | ~$1-5 |
| Total | ~$70-250/mo |
If you charge merchants 0.5% per transaction and process $500,000/month:
| Revenue Stream | Monthly |
|---|---|
| Transaction fees (0.5%) | $2,500 |
| Server cost | -$70-250 |
| Net profit | ~$2,250-2,430/mo |
Summary
XPayLabs gives you a complete multi-chain crypto payment infrastructure in a single docker compose up command. The key operational responsibilities are:
- Secure the master seed — Generate it offline, store it in a hardware wallet or encrypted vault
- Monitor service health — Watch scanner logs and gateway uptime
- Back up the database — Regular MySQL dumps
- Keep RPC endpoints healthy — Use reliable providers with failover
The SDKs (Node.js and Java), checkout UI, and merchant dashboard are open-source under MIT at github.com/yan253319066/XPayLabs. The core gateway engine is source-available under the XPay Enterprise License.
SDKs: npm | Maven Central
Top comments (0)