Deployment Guide
Comprehensive guide for deploying WiLicensor Server to various hosting platforms.
Table of Contents
- Vercel Deployment
- Heroku Deployment
- Railway Deployment
- Docker Deployment
- Production Checklist
- Database Setup
- Post-Deployment
Vercel Deployment
Vercel is optimized for Node.js applications with serverless functions.
Prerequisites
- GitHub repository
- External PostgreSQL database (Vercel doesn't provide database hosting)
- Vercel account
Database Options
Choose an external PostgreSQL provider:
| Provider | Free Tier | SSL | Notes |
|---|---|---|---|
| Neon | Yes | Yes | Serverless PostgreSQL, generous free tier |
| Supabase | Yes | Yes | PostgreSQL + additional features |
| Railway | Yes | Yes | Simple setup, good free tier |
| AWS RDS | Limited | Yes | Enterprise-grade, more complex |
Steps
1. Configure vercel.json
Already configured in repository:
{
"version": 2,
"builds": [
{
"src": "app.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/app.js"
}
]
}
2. Connect GitHub Repository
- Visit vercel.com
- Click "Add New Project"
- Import your GitHub repository
- Select the repository
3. Configure Environment Variables
In Vercel dashboard, add all variables from .env.local:
POSTGRES_HOST=your-neon-host.neon.tech
POSTGRES_PORT=5432
POSTGRES_USER=your_username
POSTGRES_PASSWORD=your_password
POSTGRES_DATABASE=your_database
POSTGRES_SSL=true
SESSION_SECRET=your_128_char_secret
EMAIL_SENDER=your-gmail@gmail.com
EMAIL_PASSWORD=your_app_password
EMAIL_FROM_ALIAS=License Server
EMAIL_RECIPIENT=admin@yourdomain.com
STRIPE_SECRET_KEY=sk_live_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
USE_STRIPE_TEST_KEY=false
SETTINGS=1
4. Deploy
git push origin main
Vercel automatically deploys on push to main branch.
5. Configure Webhooks
Update webhook URLs in payment platforms:
https://your-app.vercel.app/webhook/stripe
https://your-app.vercel.app/webhook/rainmakerai/payment-received
https://your-app.vercel.app/webhook/springboardcrm/payment-received
Heroku Deployment
Heroku provides integrated database hosting and simple deployment.
Prerequisites
- Heroku account
- Heroku CLI installed
- Git repository
Steps
1. Create Heroku App
heroku login
heroku create your-app-name
2. Add PostgreSQL Database
# Hobby Dev (free tier)
heroku addons:create heroku-postgresql:hobby-dev
# Essential (production)
heroku addons:create heroku-postgresql:essential-0
3. Configure Environment Variables
# Generate and set session secret
npm run secret # Copy output
heroku config:set SESSION_SECRET=your_generated_secret
# Email configuration
heroku config:set EMAIL_SENDER=your-gmail@gmail.com
heroku config:set EMAIL_PASSWORD=your_app_password
heroku config:set EMAIL_FROM_ALIAS="License Server"
heroku config:set EMAIL_RECIPIENT=admin@yourdomain.com
# Stripe
heroku config:set STRIPE_SECRET_KEY=sk_live_xxxxx
heroku config:set STRIPE_WEBHOOK_SECRET=whsec_xxxxx
heroku config:set USE_STRIPE_TEST_KEY=false
# Application
heroku config:set SETTINGS=1
Note: Heroku automatically sets DATABASE_URL. No need to configure individual PostgreSQL variables.
4. Deploy
git push heroku main
5. Initialize Database
# Database tables are created automatically on first run
heroku logs --tail
6. Create First Admin User
- Visit
https://your-app-name.herokuapp.com/register - Create first user (automatically becomes admin)
7. Configure Webhooks
Update webhook URLs:
https://your-app-name.herokuapp.com/webhook/stripe
Railway Deployment
Railway offers simple PostgreSQL hosting and deployment.
Prerequisites
- Railway account
- GitHub repository
Steps
1. Create New Project
- Visit railway.app
- Click "New Project"
- Select "Deploy from GitHub repo"
- Connect and select your repository
2. Add PostgreSQL Database
- Click "New" in your project
- Select "Database"
- Choose "PostgreSQL"
- Railway provides connection details automatically
3. Configure Environment Variables
In Railway dashboard, add variables:
SESSION_SECRET=your_128_char_secret
EMAIL_SENDER=your-gmail@gmail.com
EMAIL_PASSWORD=your_app_password
EMAIL_FROM_ALIAS=License Server
EMAIL_RECIPIENT=admin@yourdomain.com
STRIPE_SECRET_KEY=sk_live_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
USE_STRIPE_TEST_KEY=false
SETTINGS=1
Note: Railway automatically configures PostgreSQL connection variables.
4. Deploy
Railway deploys automatically on push to main branch.
5. Get Public URL
- Go to project settings
- Click "Generate Domain"
- Use this URL for webhooks
Docker Deployment
Containerize the application for deployment to any Docker-compatible platform.
Dockerfile
Create Dockerfile in project root:
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install --production
# Copy application files
COPY . .
# Expose port
EXPOSE 5000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD node -e "require('http').get('http://localhost:5000/api/check?term=healthcheck', (r) => {process.exit(r.statusCode === 400 ? 0 : 1)})"
# Start application
CMD ["npm", "start"]
Docker Compose
Create docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "5000:5000"
environment:
- POSTGRES_HOST=db
- POSTGRES_PORT=5432
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DATABASE=license_server
- POSTGRES_SSL=false
- SESSION_SECRET=${SESSION_SECRET}
- EMAIL_SENDER=${EMAIL_SENDER}
- EMAIL_PASSWORD=${EMAIL_PASSWORD}
- EMAIL_FROM_ALIAS=License Server
- EMAIL_RECIPIENT=${EMAIL_RECIPIENT}
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
- USE_STRIPE_TEST_KEY=false
- SETTINGS=1
depends_on:
- db
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=license_server
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:
Build and Run
Development:
docker-compose up -d
Production (single container):
# Build
docker build -t license-server .
# Run (with external database)
docker run -d \
-p 5000:5000 \
--env-file .env.local \
--name license-server \
--restart unless-stopped \
license-server
Deploy to Cloud
AWS ECS:
- Push image to ECR
- Create ECS task definition
- Configure RDS PostgreSQL
- Deploy service
Google Cloud Run:
# Build and push
gcloud builds submit --tag gcr.io/PROJECT_ID/license-server
# Deploy
gcloud run deploy license-server \
--image gcr.io/PROJECT_ID/license-server \
--platform managed \
--region us-central1 \
--allow-unauthenticated
Production Checklist
Before deploying to production, verify all items:
Security
- Strong
SESSION_SECRET(128+ characters) - PostgreSQL SSL enabled (
POSTGRES_SSL=true) - Production Stripe keys configured
- Gmail App-Specific Password used
- All secrets secured (not in version control)
- HTTPS enabled on hosting platform
- CORS configured if needed
Database
- PostgreSQL 12+ with SSL
- Automated backups configured
- Connection pooling enabled
- Database credentials rotated regularly
-
session_pgtable created automatically
- SMTP credentials tested (
node test.js) -
EMAIL_RECIPIENTset to admin email - App-Specific Password generated
- Email delivery working
Payment Webhooks
- Webhook URLs configured in Stripe
- Webhook secrets match configuration
- Test webhooks with Stripe CLI
- RainmakerAI/SpringboardCRM webhooks configured (if used)
Monitoring
- Error logging configured
- Uptime monitoring set up
- Database performance monitoring
- Email notification alerts
Documentation
- Update API documentation with production URLs
- Document deployment process
- Create runbook for common issues
- Train team on admin dashboard
Database Setup
External PostgreSQL Setup
Most hosting platforms require external PostgreSQL. Choose a provider and create database:
Neon (Recommended for Vercel):
- Visit neon.tech
- Create new project
- Copy connection string
- Parse into environment variables:
Becomes:postgresql://user:password@host:5432/database?sslmode=requirePOSTGRES_HOST=host POSTGRES_USER=user POSTGRES_PASSWORD=password POSTGRES_DATABASE=database POSTGRES_SSL=true
Supabase:
- Visit supabase.com
- Create new project
- Go to Settings → Database
- Copy connection pooler details
- Use "Transaction" mode
Database Migration
If migrating from existing database:
1. Backup existing database:
pg_dump -h old-host -U old-user -d old-database > backup.sql
2. Create new database on hosting platform
3. Restore backup:
psql -h new-host -U new-user -d new-database < backup.sql
4. Update connection strings in environment variables
5. Test connection:
psql -h new-host -U new-user -d new-database -c "SELECT COUNT(*) FROM users;"
Post-Deployment
Verify Deployment
1. Test Application:
curl https://your-app.com/api/check?term=test
Expected: 400 error (test key doesn't exist)
2. Create Admin User:
- Visit
https://your-app.com/register - Create first admin user
- Verify login works
3. Test Admin Dashboard:
- Create a product
- Generate a test key
- Verify key validation works
4. Test Email:
- Trigger key generation with trial product
- Verify email received
5. Test Webhooks:
# Stripe CLI
stripe listen --forward-to https://your-app.com/webhook/stripe
stripe trigger customer.subscription.created
Monitoring Setup
Application Monitoring:
Uptime Monitoring:
- UptimeRobot - Free uptime checks
- Pingdom - Advanced monitoring
- StatusCake - Status pages
Database Monitoring:
- Built-in platform monitoring (Heroku, Railway, etc.)
- pganalyze - PostgreSQL monitoring
- Datadog - Infrastructure monitoring
Backup Strategy
Database Backups:
# Daily automated backups
0 2 * * * pg_dump -h host -U user -d database > /backups/db_$(date +\%Y\%m\%d).sql
Configuration Backups:
- Store environment variables in secure password manager
- Document all configuration changes
- Keep deployment runbook updated
Scaling Considerations
Horizontal Scaling:
- Use load balancer (AWS ALB, Cloudflare Load Balancing)
- Multiple app instances
- Shared PostgreSQL database
- Shared session store
Vertical Scaling:
- Upgrade database instance (more CPU/RAM)
- Increase connection pool size
- Optimize database queries
Caching:
- Add Redis for session storage
- Cache frequently accessed data
- Use CDN for static assets
Related Documentation
- ← Back to README
- Configuration Guide
- API Documentation
- Development Guide
- Troubleshooting Guide
- Technical Details
Last Updated: 2025-12-18