Production Checklist
Before deploying to production, ensure you’ve completed these critical steps:
Security Configuration
CRITICAL: Generate a strong, random JWT secret:node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Update .env:JWT_SECRET="your-generated-secret-here"
Never use the default JWT secret in production! This would allow attackers to forge authentication tokens.
All production deployments must use HTTPS:Option 1: Reverse Proxy (nginx)server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# Client
location / {
root /path/to/client/dist;
try_files $uri $uri/ /index.html;
}
# API
location /api {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# WebSocket
location /socket.io {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
Option 2: Let’s Encrypt (Certbot)sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com
- Use strong database passwords (32+ random characters)
- Enable SSL/TLS for database connections
- Restrict database access to application servers only
- Use connection pooling (Supabase pooler or PgBouncer)
- Enable automatic backups
Supabase SSL Connection:DATABASE_URL="postgresql://user:pass@host:6543/db?sslmode=require"
- Never commit
.env files to version control
- Use platform-specific secrets management:
- Vercel: Environment Variables in dashboard
- Railway: Environment Variables in project settings
- Docker: Use
docker-compose.override.yml (gitignored)
- Rotate secrets regularly
- Use different secrets for different environments
Database Optimization
Apply all database migrations before starting the server:Verify schema is up to date:cd server
npx prisma migrate status
Enable Connection Pooling
For Supabase, use the Transaction pooler:DATABASE_URL="postgresql://postgres.xxx:pass@aws-0-region.pooler.supabase.com:6543/postgres"
For self-hosted, configure PgBouncer (see Database Setup).
Automated backups (cron):# Add to crontab: daily backup at 2 AM
0 2 * * * /usr/bin/docker exec neuron-meet-db pg_dump -U neuronmeet neuronmeet | gzip > /backups/neuronmeet-$(date +\%Y\%m\%d).sql.gz
Supabase: Backups are automatic on paid plans. WebRTC Configuration
Self-Host coturn (Optional)
Install coturn on your server:Configure /etc/turnserver.conf:listening-port=3478
tls-listening-port=5349
listening-ip=YOUR_SERVER_IP
external-ip=YOUR_SERVER_IP
realm=yourdomain.com
server-name=yourdomain.com
lt-cred-mech
user=username:password
no-tcp-relay
no-multicast-peers
cert=/path/to/cert.pem
pkey=/path/to/key.pem
Enable and start:sudo systemctl enable coturn
sudo systemctl start coturn
Performance Optimization
Set environment to production:This enables:
- Optimized builds
- Reduced logging
- Better error handling
- Performance optimizations
Build both client and server:This runs:
- Client: Vite production build with minification and tree-shaking
- Server: NestJS compilation with TypeScript optimization
Monitoring & Logging
The server includes a health check endpoint:Configure uptime monitoring:
View logs by platform:Docker:docker-compose logs -f server
Railway:
View in Railway dashboard > Deployments > LogsPM2 (VPS):
Consider integrating error tracking:
Docker Production Deployment
Update docker-compose.yml
Ensure production settings in docker-compose.yml:environment:
NODE_ENV: production
JWT_SECRET: ${JWT_SECRET} # From .env file
Build and start services
docker-compose up -d --build
Verify services
All services should show “Up” status.
Vercel Deployment
Vercel is configured via vercel.json:
Set environment variables
In Vercel dashboard, add:
VITE_API_URL - Your backend API URL
VITE_WS_URL - Your backend WebSocket URL
Vercel configuration includes security headers:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Railway Deployment
Railway is configured via railway.json:
Connect repository
- Create Railway account
- New Project > Deploy from GitHub
- Select your repository
Add PostgreSQL
- Click “New Service” > Database > PostgreSQL
- Railway automatically provides
DATABASE_URL
Deploy
Railway automatically deploys on push to main branch.Configuration from railway.json:
- Build:
npm run build:production
- Start:
npm run start:production
- Health check:
/api/health (timeout: 100s)
- Restart policy: ON_FAILURE (max 10 retries)
Manual VPS Deployment
For custom infrastructure:
Set up server
Requirements:
- Ubuntu 20.04+ or similar
- Node.js 18+
- PostgreSQL 15+
- nginx (reverse proxy)
- PM2 (process manager)
Install dependencies
# Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# PM2
sudo npm install -g pm2
# nginx
sudo apt install -y nginx
# PostgreSQL
sudo apt install -y postgresql postgresql-contrib
Clone and build
git clone <repository-url>
cd neuron-meet
npm run install:all
npm run build
Configure PM2
Create ecosystem.config.js:module.exports = {
apps: [{
name: 'neuron-meet',
cwd: './server',
script: 'dist/main.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3001
}
}]
};
Start with PM2:pm2 start ecosystem.config.js
pm2 save
pm2 startup
Configure nginx
See the nginx configuration in Step 1 > Security Configuration > Enable HTTPS/TLSEnable and restart:sudo ln -s /etc/nginx/sites-available/neuron-meet /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Scaling Considerations
Horizontal Scaling
For high traffic, scale across multiple servers:
Use nginx or a cloud load balancer:upstream backend {
least_conn;
server backend1.example.com:3001;
server backend2.example.com:3001;
server backend3.example.com:3001;
}
server {
location /api {
proxy_pass http://backend;
}
}
WebSocket Sticky Sessions
For WebSocket connections, enable sticky sessions:upstream backend {
ip_hash; # Sticky sessions based on IP
server backend1.example.com:3001;
server backend2.example.com:3001;
}
Or use Redis adapter for Socket.IO to share connections across servers.
- Enable read replicas for read-heavy workloads
- Use connection pooling (PgBouncer or Supabase pooler)
- Consider database sharding for very large scale
- Monitor query performance with Prisma logging
Vertical Scaling
Optimize resource usage:
- CPU: Use PM2 cluster mode to utilize all cores
- Memory: Monitor with
pm2 monit and adjust limits
- Database: Increase connection pool size for high concurrency
Security Hardening
These security measures are critical for production deployments.
Protect against abuse with rate limiting:# In nginx config
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location /api {
limit_req zone=api burst=20 nodelay;
proxy_pass http://localhost:3001;
}
In production, restrict CORS to your frontend domain:// server/src/main.ts
app.enableCors({
origin: process.env.FRONTEND_URL,
credentials: true
});
Only expose necessary ports:sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
PostgreSQL and Node.js ports should only be accessible internally.
Post-Deployment Testing
Verify HTTPS
Test SSL/TLS configuration:curl -I https://yourdomain.com
Check SSL grade at SSL Labs Test API endpoints
# Health check
curl https://yourdomain.com/api/health
# Should return: {"status":"ok"}
Test WebRTC connectivity
- Create a test room
- Join from different networks (WiFi, mobile)
- Verify video/audio works
- Test screen sharing
- Verify TURN server is used in restrictive networks
Load testing
Use tools like Apache Bench or Artillery:ab -n 1000 -c 10 https://yourdomain.com/api/health
Maintenance
Updates and Patches
git pull origin main
npm run install:all
npm run build
Monitoring Checklist
Server uptime and response times
Database connection pool usage
Disk space and database size
SSL certificate expiration
Error rates and exceptions
Troubleshooting
WebSocket connections failing
- Verify nginx WebSocket proxy configuration
- Check CORS settings allow WebSocket upgrade
- Ensure sticky sessions are enabled for load balancing
- Check firewall allows WebSocket traffic
Database connection errors
- Verify connection string and credentials
- Check connection pool limits
- Ensure database is accessible from app server
- Review Prisma connection logs
- Verify TURN server is configured and accessible
- Check browser console for WebRTC errors
- Test with different networks (WiFi, mobile, VPN)
- Verify HTTPS is enabled (required for WebRTC)
Support
For deployment issues:
- Check application logs
- Review Environment Variables
- Verify Database Setup
- Consult platform documentation (Vercel, Railway, etc.)
Need Help?
If you encounter issues not covered in this guide, please open an issue on the GitHub repository with:
- Deployment platform
- Error logs
- Configuration (with secrets redacted)