Security Hardening
Production checklist for deploying PayWarden securely.
Pre-launch checklist
Secrets
- [ ]
VAULT_KEYis 32 random bytes (openssl rand -hex 32), not a human-readable password - [ ]
VAULT_KEYis backed up offline in a secure location (password manager, HSM, or printed and locked) - [ ]
API_KEYis unique and not reused from development - [ ]
.envis not committed to git (check.gitignore) - [ ] Mnemonic phrase is written down and stored offline — not in any digital system
Network
- [ ] PayWarden runs behind a reverse proxy (Nginx, Caddy, or Cloudflare Tunnel)
- [ ] Direct port 3000 is not exposed to the internet
- [ ] HTTPS is enforced — all webhook URLs use
https:// - [ ] Cloudflare or similar DDoS protection is enabled
Server
- [ ] Server has a firewall — only ports 80, 443, and 22 are open
- [ ] SSH uses key-based auth only (no password auth)
- [ ] Automatic security updates are enabled
- [ ] Server is not running other public-facing services on the same machine
Docker
- [ ] Containers run as non-root users
- [ ]
vault.encis mounted as a volume outside the container image - [ ] Docker socket is not exposed to the app container
- [ ]
restart: alwaysis set for production
Key rotation
Rotating VAULT_KEY
If you suspect VAULT_KEY is compromised:
bash
# 1. Generate a new key
openssl rand -hex 32 # → NEW_VAULT_KEY
# 2. Decrypt the vault with the old key
# (requires vault-rotate script — coming in v1.1)
# 3. Re-encrypt with the new key
# 4. Update VAULT_KEY in .env
# 5. Restart the app
docker compose restart appWARNING
Never change VAULT_KEY without re-encrypting vault.enc. If VAULT_KEY and vault.enc are out of sync, the app will fail to start.
Rotating API keys
API keys can be rotated without downtime:
- Create a new API key via the admin dashboard
- Update
API_KEYin your backend's environment - Delete the old API key once confirmed working
Rate limiting
PayWarden applies rate limiting to all endpoints:
| Endpoint | Limit |
|---|---|
POST /payments | 60 req/min per API key |
GET /payments | 120 req/min per API key |
GET /checkout/:id/status | 60 req/min per IP |
POST /admin/login | 5 req/min per IP |
For higher limits, configure a Redis-backed rate limiter in front of the gateway.
Webhook security
- Always verify the
X-PayWarden-Signatureheader before processing webhooks - Respond within 5 seconds — use a queue if processing takes longer
- Use
X-Idempotency-Keyto deduplicate retried deliveries - Your webhook endpoint should be HTTPS only
Monitoring
Set up alerts for:
- App container health check failures
- PostgreSQL disk usage > 80%
- Failed webhook deliveries (check admin dashboard)
- Hot wallet TRX balance drops below
GAS_LOW_THRESHOLD - Unusual order volume spikes
Incident response
If you suspect a breach:
- Immediately rotate
API_KEY— this cuts off attacker API access - Check
order_eventstable for unauthorized orders - Check admin logs for unauthorized login attempts
- If
VAULT_KEYmay be compromised, rotate it (see above) - If the mnemonic is compromised, sweep all funds to a new wallet immediately
The mnemonic is the ultimate key to all funds. Protecting it is the highest priority.