Deployment Guide - RumenDamyanov/js-chess GitHub Wiki
Deployment Guide
Deploy your JS Chess application to production with proper configuration, security, and monitoring.
Overview
This guide covers deploying the JS Chess project using Docker containers, configuring Nginx as a reverse proxy, and setting up production environments.
Production Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Load Balancer │ -> │ Nginx Proxy │ -> │ Frontend │
│ (Optional) │ │ Port 80/443 │ │ Port 3000 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
┌─────────────────┐
│ Go Backend │
│ Port 8080 │
└─────────────────┘
Prerequisites
- Docker and Docker Compose installed
- Domain name pointed to your server
- SSL certificate (Let's Encrypt recommended)
- At least 1GB RAM, 1 CPU core
- 10GB disk space
Production Deployment
1. Clone and Setup
git clone --recursive https://github.com/RumenDamyanov/js-chess.git
cd js-chess
make setup
2. Environment Configuration
Create production environment file:
cp .env.example .env.production
Edit .env.production
:
NODE_ENV=production
API_URL=https://api.yourdomain.com
FRONTEND_URL=https://yourdomain.com
SSL_ENABLED=true
DOMAIN=yourdomain.com
[email protected]
3. SSL Certificate Setup
Using Let's Encrypt with Certbot:
# Install certbot
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
# Get SSL certificate
sudo certbot --nginx -d yourdomain.com -d api.yourdomain.com
# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet
4. Production Build
# Build all components
make build-prod
# Start production stack
make deploy-prod
Docker Production Configuration
Docker Compose Production
Create docker-compose.prod.yml
:
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/prod.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/ssl
restart: unless-stopped
depends_on:
- frontend
- backend
frontend:
build:
context: .
dockerfile: Dockerfile.prod
environment:
- NODE_ENV=production
restart: unless-stopped
expose:
- "3000"
backend:
image: rumenx/go-chess:latest
environment:
- GIN_MODE=release
- PORT=8080
restart: unless-stopped
expose:
- "8080"
redis:
image: redis:alpine
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis_data:/data
volumes:
redis_data:
Production Dockerfile
# Multi-stage build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Production image
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Nginx Configuration
Main Configuration
Create nginx/prod.conf
:
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=general:10m rate=100r/m;
# Frontend server
server {
listen 80;
listen [::]:80;
server_name yourdomain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com;
# SSL configuration
ssl_certificate /etc/ssl/certs/yourdomain.com.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
# Frontend files
location / {
proxy_pass http://frontend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# API proxy
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket proxy
location /ws/ {
proxy_pass http://backend:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Static assets caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Health check
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
Environment-Specific Configurations
Development Environment
# Development with hot reload
make dev
# Development with Docker
make dev-docker
Staging Environment
# Staging deployment
make deploy-staging
# Staging tests
make test-staging
Production Environment
# Production deployment
make deploy-prod
# Production health check
make health-prod
# Production logs
make logs-prod
Security Configuration
Firewall Setup
# UFW firewall configuration
sudo ufw enable
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Fail2ban for additional protection
sudo apt-get install fail2ban
Environment Variables
Store sensitive data in environment variables:
# Database (if using)
DB_HOST=localhost
DB_USER=chess_user
DB_PASSWORD=secure_password
DB_NAME=chess_db
# API Keys
JWT_SECRET=your_jwt_secret_here
REDIS_URL=redis://localhost:6379
# Monitoring
SENTRY_DSN=your_sentry_dsn
Docker Secrets
For sensitive data in Docker:
services:
backend:
image: rumenx/go-chess:latest
secrets:
- db_password
- jwt_secret
secrets:
db_password:
file: ./secrets/db_password.txt
jwt_secret:
file: ./secrets/jwt_secret.txt
Monitoring and Logging
Health Checks
# Check all services
make health-check
# Individual service checks
curl https://yourdomain.com/health
curl https://api.yourdomain.com/health
Log Management
# View logs
make logs
# Follow logs
make logs-follow
# Log rotation
sudo logrotate -f /etc/logrotate.d/nginx
Monitoring Setup
Add monitoring with Prometheus and Grafana:
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
Performance Optimization
CDN Configuration
Use a CDN for static assets:
# CDN headers
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header CDN-Cache-Control "public, max-age=31536000";
}
Database Optimization
If using a database:
-- Create indexes for better performance
CREATE INDEX idx_games_created_at ON games(created_at);
CREATE INDEX idx_moves_game_id ON moves(game_id);
Caching Strategy
Implement Redis caching:
// Cache game states
func (s *GameService) GetGame(id int) (*Game, error) {
// Check cache first
if cached := s.cache.Get(fmt.Sprintf("game:%d", id)); cached != nil {
return cached.(*Game), nil
}
// Fetch from database
game, err := s.db.GetGame(id)
if err != nil {
return nil, err
}
// Cache result
s.cache.Set(fmt.Sprintf("game:%d", id), game, 5*time.Minute)
return game, nil
}
Backup and Recovery
Database Backup
# Automated backup script
#!/bin/bash
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# PostgreSQL backup
pg_dump chess_db > $BACKUP_DIR/chess_db_$DATE.sql
# Compress and encrypt
tar -czf $BACKUP_DIR/chess_backup_$DATE.tar.gz $BACKUP_DIR/chess_db_$DATE.sql
gpg --encrypt --recipient [email protected] $BACKUP_DIR/chess_backup_$DATE.tar.gz
# Clean old backups
find $BACKUP_DIR -name "chess_backup_*.tar.gz.gpg" -mtime +30 -delete
Disaster Recovery
# Full system restore
make restore-from-backup
# Database restore
pg_restore -d chess_db backup_file.sql
Continuous Deployment
GitHub Actions
Create .github/workflows/deploy.yml
:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Deploy to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /opt/js-chess
git pull --recurse-submodules
make deploy-prod
Rolling Updates
# Zero-downtime deployment
make deploy-rolling
# Rollback if needed
make rollback
Troubleshooting
Common Issues
-
SSL Certificate Issues
# Renew certificate sudo certbot renew # Test certificate sudo nginx -t sudo systemctl reload nginx
-
Container Issues
# Check container status docker ps -a # View container logs docker logs container_name # Restart services make restart-prod
-
Performance Issues
# Monitor resource usage htop docker stats # Check Nginx status sudo systemctl status nginx
Log Analysis
# Analyze access logs
tail -f /var/log/nginx/access.log | grep -v "200"
# Error log analysis
tail -f /var/log/nginx/error.log
# Application logs
docker logs js-chess_backend_1 --follow
Maintenance
Regular Tasks
# Daily maintenance
make daily-maintenance
# Weekly maintenance
make weekly-maintenance
# Monthly maintenance
make monthly-maintenance
Updates
# Update system packages
sudo apt update && sudo apt upgrade
# Update Docker images
make update-images
# Update application
git pull --recurse-submodules
make deploy-prod
For more detailed deployment information, see the Advanced Deployment guide.