Nginx Configuration - RumenDamyanov/js-chess GitHub Wiki
Comprehensive guide for configuring Nginx as a reverse proxy, load balancer, and web server for the chess showcase application.
This guide covers:
- Basic Nginx setup and configuration
- Reverse proxy configuration for Node.js applications
- SSL/TLS termination and certificate management
- Load balancing across multiple instances
- Static file serving and caching
- WebSocket proxy configuration
- Security hardening and rate limiting
- Performance optimization
- Monitoring and logging
# Ubuntu/Debian
sudo apt update
sudo apt install nginx
# CentOS/RHEL
sudo yum install epel-release
sudo yum install nginx
# macOS (for development)
brew install nginx
# Start and enable Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# Check status
sudo systemctl status nginx
# Main configuration files
/etc/nginx/
├── nginx.conf # Main configuration file
├── sites-available/ # Available site configurations
├── sites-enabled/ # Enabled site configurations (symlinks)
├── conf.d/ # Additional configuration files
├── ssl/ # SSL certificates and keys
├── snippets/ # Reusable configuration snippets
└── modules-enabled/ # Enabled modules
# Log files
/var/log/nginx/
├── access.log # Access logs
├── error.log # Error logs
└── chess-showcase.log # Application-specific logs
# Web root
/var/www/html/ # Default web root
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
# Load dynamic modules
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
# MIME types
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging Format
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
log_format chess_detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" "$http_x_real_ip" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time" '
'game_id="$arg_gameId" player_id="$cookie_playerId"';
# Logging
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Brotli Compression (if module available)
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# Rate Limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=websocket:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=static:10m rate=50r/s;
# Connection Limiting
limit_conn_zone $binary_remote_addr zone=addr:10m;
# Map for WebSocket upgrade
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Upstream definitions
include /etc/nginx/conf.d/upstreams.conf;
# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
# /etc/nginx/conf.d/upstreams.conf
# Main application servers
upstream chess_app {
least_conn;
server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3002 max_fails=3 fail_timeout=30s;
# Health check (requires nginx-plus or custom module)
# health_check interval=30s fails=3 passes=2;
keepalive 32;
}
# WebSocket servers
upstream chess_websocket {
ip_hash; # Ensure sticky sessions for WebSocket
server 127.0.0.1:3010 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3011 max_fails=3 fail_timeout=30s;
keepalive 16;
}
# API servers (if separate from main app)
upstream chess_api {
least_conn;
server 127.0.0.1:4000 weight=3 max_fails=3 fail_timeout=30s;
server 127.0.0.1:4001 weight=3 max_fails=3 fail_timeout=30s;
server 127.0.0.1:4002 weight=1 max_fails=3 fail_timeout=30s backup;
keepalive 32;
}
# /etc/nginx/sites-available/chess-showcase
server {
listen 80;
server_name chessgame.com www.chessgame.com;
# Redirect all HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name chessgame.com www.chessgame.com;
# SSL Configuration
ssl_certificate /etc/nginx/ssl/chessgame.com.crt;
ssl_certificate_key /etc/nginx/ssl/chessgame.com.key;
ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.crt;
# Include SSL security settings
include /etc/nginx/snippets/ssl-params.conf;
include /etc/nginx/snippets/security-headers.conf;
# Logging
access_log /var/log/nginx/chess-showcase.log chess_detailed;
error_log /var/log/nginx/chess-showcase-error.log;
# Basic settings
root /var/www/chess-showcase;
index index.html;
# Connection limits
limit_conn addr 10;
# Security settings
client_max_body_size 10M;
client_body_timeout 60s;
client_header_timeout 60s;
# Static files with caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header X-Content-Type-Options nosniff;
# CORS for fonts and assets
add_header Access-Control-Allow-Origin *;
# Try static files first, then fallback to app
try_files $uri @app;
# Rate limiting for static files
limit_req zone=static burst=20 nodelay;
# Enable gzip for text-based assets
gzip_static on;
}
# API endpoints
location /api/ {
# Rate limiting for API
limit_req zone=api burst=20 nodelay;
# Proxy headers
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Proxy buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
# Pass to application
proxy_pass http://chess_app;
# Health check exclusion
if ($request_uri ~ "^/api/health") {
access_log off;
}
}
# WebSocket connections
location /socket.io/ {
# Rate limiting for WebSocket
limit_req zone=websocket burst=10 nodelay;
# WebSocket headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $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;
# WebSocket timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 3600s; # Long timeout for persistent connections
# Disable buffering for real-time communication
proxy_buffering off;
# Pass to WebSocket servers
proxy_pass http://chess_websocket;
}
# Framework-specific routes
location /react/ {
alias /var/www/chess-showcase/react/;
try_files $uri $uri/ /react/index.html;
# SPA routing support
location ~ ^/react/(?!static/).* {
try_files $uri /react/index.html;
}
}
location /vue/ {
alias /var/www/chess-showcase/vue/;
try_files $uri $uri/ /vue/index.html;
location ~ ^/vue/(?!static/).* {
try_files $uri /vue/index.html;
}
}
location /angular/ {
alias /var/www/chess-showcase/angular/;
try_files $uri $uri/ /angular/index.html;
location ~ ^/angular/(?!static/).* {
try_files $uri /angular/index.html;
}
}
location /vanilla/ {
alias /var/www/chess-showcase/vanilla/;
try_files $uri $uri/ /vanilla/index.html;
}
# Main application (default framework)
location / {
try_files $uri $uri/ @app;
}
# Application fallback
location @app {
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;
proxy_pass http://chess_app;
}
# Health check endpoint (no rate limiting)
location = /health {
access_log off;
proxy_pass http://chess_app;
}
# Block access to sensitive files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~ \.(env|log|sql)$ {
deny all;
access_log off;
log_not_found off;
}
# Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /404.html {
root /var/www/chess-showcase/errors;
internal;
}
location = /50x.html {
root /var/www/chess-showcase/errors;
internal;
}
}
# /etc/nginx/sites-available/chess-showcase-dev
server {
listen 80;
server_name localhost dev.chessgame.local;
access_log /var/log/nginx/chess-dev.log main;
error_log /var/log/nginx/chess-dev-error.log debug;
# Allow larger uploads in development
client_max_body_size 50M;
# Development static files (no caching)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
# CORS for development
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
try_files $uri @dev_app;
}
# API with CORS
location /api/ {
# CORS preflight
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization";
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain charset=UTF-8';
add_header Content-Length 0;
return 204;
}
# CORS headers
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
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;
proxy_pass http://127.0.0.1:3000;
}
# WebSocket for development
location /socket.io/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $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_pass http://127.0.0.1:3001;
}
# Development servers for each framework
location /react-dev/ {
proxy_pass http://127.0.0.1:3010/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /vue-dev/ {
proxy_pass http://127.0.0.1:3020/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /angular-dev/ {
proxy_pass http://127.0.0.1:3030/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# Default to main dev server
location / {
try_files $uri @dev_app;
}
location @dev_app {
proxy_pass http://127.0.0.1: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;
}
}
# /etc/nginx/snippets/ssl-params.conf
# SSL Protocol and Ciphers
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# SSL Session Settings
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# DH Parameters
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# SSL Buffer Size
ssl_buffer_size 4k;
# /etc/nginx/snippets/security-headers.conf
# Strict Transport Security
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' wss: ws:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always;
# Other Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# Remove server signature
server_tokens off;
more_clear_headers Server;
# /etc/nginx/conf.d/rate-limiting.conf
# Define rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=signup:10m rate=2r/m;
limit_req_zone $binary_remote_addr zone=api_strict:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=api_general:10m rate=100r/m;
# Connection limiting
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
# Define map for rate limiting bypass
map $http_user_agent $limit_key {
~*bot 0;
~*crawler 0;
default $binary_remote_addr;
}
# Rate limiting for specific endpoints
map $request_uri $api_limit_zone {
~*/api/auth/login login;
~*/api/auth/signup signup;
~*/api/games/create api_strict;
~*/api/ api_general;
default "";
}
# /etc/nginx/conf.d/advanced-upstreams.conf
# Main application with health checks
upstream chess_app_primary {
# Load balancing method
least_conn;
# Primary servers
server app1.internal:3000 weight=3 max_fails=2 fail_timeout=30s;
server app2.internal:3000 weight=3 max_fails=2 fail_timeout=30s;
server app3.internal:3000 weight=2 max_fails=2 fail_timeout=30s;
# Backup server
server app-backup.internal:3000 backup;
# Keep-alive connections
keepalive 32;
keepalive_requests 100;
keepalive_timeout 60s;
}
# Geographic load balancing
upstream chess_app_us {
server us-east-app1.internal:3000;
server us-east-app2.internal:3000;
server us-west-app1.internal:3000;
}
upstream chess_app_eu {
server eu-west-app1.internal:3000;
server eu-west-app2.internal:3000;
}
# Map for geographic routing
map $geoip_country_code $backend_pool {
default chess_app_primary;
US chess_app_us;
CA chess_app_us;
GB chess_app_eu;
DE chess_app_eu;
FR chess_app_eu;
}
# Health check configuration (requires nginx-plus)
location /health-check {
access_log off;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
proxy_pass http://chess_app;
proxy_connect_timeout 3s;
proxy_read_timeout 3s;
# Custom health check
proxy_set_header Host $host;
proxy_set_header User-Agent "nginx-health-check";
}
# Simple health check for open source nginx
location /nginx-health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# /etc/nginx/conf.d/caching.conf
# Proxy cache path
proxy_cache_path /var/cache/nginx/chess
levels=1:2
keys_zone=chess_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
# FastCGI cache path (if using PHP)
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=chess_fastcgi:10m
max_size=1g
inactive=60m;
# Cache configuration for different content types
map $sent_http_content_type $expires {
default off;
text/html 5m;
text/css 1y;
application/javascript 1y;
~image/ 1M;
~font/ 1y;
application/pdf 1M;
application/json 1h;
}
# Proxy cache configuration
server {
# ... other configuration ...
location /api/games/ {
# Cache GET requests only
proxy_cache chess_cache;
proxy_cache_methods GET HEAD;
proxy_cache_key $scheme$proxy_host$request_uri$is_args$args;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
# Cache headers
add_header X-Cache-Status $upstream_cache_status;
proxy_cache_bypass $http_pragma $http_authorization;
proxy_no_cache $http_pragma $http_authorization;
# Only cache for anonymous users
set $no_cache 0;
if ($http_authorization) {
set $no_cache 1;
}
proxy_cache_bypass $no_cache;
proxy_no_cache $no_cache;
proxy_pass http://chess_app;
}
}
# Microcaching for dynamic content
location / {
proxy_cache chess_cache;
proxy_cache_valid 200 1s;
proxy_cache_key $scheme$proxy_host$request_uri$is_args$args$http_user_agent;
# Add cache status header
add_header X-Cache-Status $upstream_cache_status;
# Bypass cache for logged-in users
set $skip_cache 0;
if ($http_cookie ~* "logged_in") {
set $skip_cache 1;
}
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_pass http://chess_app;
}
# WebSocket-specific configuration
location /socket.io/ {
# Rate limiting
limit_req zone=websocket burst=10 nodelay;
# WebSocket headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $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;
# Sticky sessions for WebSocket
proxy_set_header X-Session-ID $cookie_sessionid;
# Timeouts for persistent connections
proxy_connect_timeout 4s;
proxy_send_timeout 60s;
proxy_read_timeout 3600s;
# Buffer settings
proxy_buffering off;
proxy_request_buffering off;
# Pass to WebSocket upstream
proxy_pass http://chess_websocket;
# Error handling
proxy_intercept_errors on;
error_page 502 503 504 /websocket_error.html;
}
# WebSocket error page
location = /websocket_error.html {
root /var/www/chess-showcase/errors;
internal;
}
# Custom log formats
log_format chess_performance '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time '
'uct="$upstream_connect_time" '
'uht="$upstream_header_time" '
'urt="$upstream_response_time" '
'cache="$upstream_cache_status" '
'gzip_ratio="$gzip_ratio"';
log_format chess_security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" '
'ssl_protocol="$ssl_protocol" '
'ssl_cipher="$ssl_cipher" '
'request_length="$request_length" '
'connection="$connection" '
'connection_requests="$connection_requests"';
# Conditional logging
map $status $log_4xx_5xx {
~^[45] 1;
default 0;
}
# Access log with conditions
access_log /var/log/nginx/chess-performance.log chess_performance;
access_log /var/log/nginx/chess-security.log chess_security;
access_log /var/log/nginx/chess-errors.log chess_performance if=$log_4xx_5xx;
# Real-time metrics endpoint
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
# Prometheus metrics (requires nginx-prometheus-exporter)
location /metrics {
access_log off;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
# Proxy to metrics exporter
proxy_pass http://127.0.0.1:9113/metrics;
}
# nginx.conf additions for performance
events {
worker_connections 4096;
use epoll;
multi_accept on;
accept_mutex off;
}
http {
# Keep-alive settings
keepalive_timeout 65;
keepalive_requests 1000;
# File handling
sendfile on;
sendfile_max_chunk 1m;
tcp_nopush on;
tcp_nodelay on;
# Buffer settings
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
# Timeouts
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
# Hash tables
server_names_hash_bucket_size 64;
types_hash_max_size 2048;
}
# HTTP/2 specific optimizations
server {
listen 443 ssl http2;
# HTTP/2 push
location = /index.html {
http2_push /css/main.css;
http2_push /js/main.js;
http2_push /fonts/chess-icons.woff2;
}
# HTTP/2 settings
http2_max_field_size 4k;
http2_max_header_size 16k;
http2_max_requests 1000;
}
#!/bin/bash
# nginx-chess-admin.sh
set -e
NGINX_CONF="/etc/nginx"
SITES_AVAILABLE="$NGINX_CONF/sites-available"
SITES_ENABLED="$NGINX_CONF/sites-enabled"
LOGDIR="/var/log/nginx"
case "$1" in
enable)
if [ -z "$2" ]; then
echo "Usage: $0 enable <site-name>"
exit 1
fi
SITE="$2"
if [ ! -f "$SITES_AVAILABLE/$SITE" ]; then
echo "Site $SITE not found in sites-available"
exit 1
fi
ln -sf "$SITES_AVAILABLE/$SITE" "$SITES_ENABLED/"
echo "Site $SITE enabled"
nginx -t && systemctl reload nginx
;;
disable)
if [ -z "$2" ]; then
echo "Usage: $0 disable <site-name>"
exit 1
fi
SITE="$2"
rm -f "$SITES_ENABLED/$SITE"
echo "Site $SITE disabled"
nginx -t && systemctl reload nginx
;;
test)
echo "Testing nginx configuration..."
nginx -t
;;
reload)
echo "Reloading nginx..."
nginx -t && systemctl reload nginx
;;
status)
systemctl status nginx
;;
logs)
SITE="${2:-chess-showcase}"
tail -f "$LOGDIR/$SITE.log"
;;
error-logs)
SITE="${2:-chess-showcase}"
tail -f "$LOGDIR/$SITE-error.log"
;;
cert-renew)
echo "Renewing SSL certificates..."
certbot renew --quiet
nginx -t && systemctl reload nginx
;;
backup-config)
BACKUP_DIR="/backup/nginx/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
cp -r "$NGINX_CONF" "$BACKUP_DIR/"
echo "Configuration backed up to $BACKUP_DIR"
;;
*)
echo "Usage: $0 {enable|disable|test|reload|status|logs|error-logs|cert-renew|backup-config}"
exit 1
;;
esac
#!/bin/bash
# ssl-management.sh
DOMAIN="chessgame.com"
SSL_DIR="/etc/nginx/ssl"
EMAIL="[email protected]"
setup_letsencrypt() {
echo "Setting up Let's Encrypt for $DOMAIN..."
# Install certbot
sudo apt update
sudo apt install certbot python3-certbot-nginx
# Get certificate
sudo certbot --nginx -d "$DOMAIN" -d "www.$DOMAIN" --email "$EMAIL" --agree-tos --non-interactive
# Setup auto-renewal
echo "0 12 * * * /usr/bin/certbot renew --quiet" | sudo crontab -
}
generate_dhparam() {
echo "Generating DH parameters..."
sudo openssl dhparam -out "$SSL_DIR/dhparam.pem" 2048
}
check_cert_expiry() {
echo "Checking certificate expiry for $DOMAIN..."
echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 2>/dev/null | openssl x509 -noout -dates
}
case "$1" in
setup)
setup_letsencrypt
generate_dhparam
;;
renew)
sudo certbot renew
sudo systemctl reload nginx
;;
check)
check_cert_expiry
;;
dhparam)
generate_dhparam
;;
*)
echo "Usage: $0 {setup|renew|check|dhparam}"
exit 1
;;
esac
# Check nginx configuration
nginx -t
# Test specific site configuration
nginx -t -c /etc/nginx/sites-available/chess-showcase
# Check nginx status
systemctl status nginx
# View nginx error logs
tail -f /var/log/nginx/error.log
# Check listening ports
ss -tulpn | grep nginx
# Monitor nginx processes
ps aux | grep nginx
# Check file permissions
ls -la /etc/nginx/sites-available/
ls -la /var/www/chess-showcase/
# Test upstream connectivity
curl -I http://127.0.0.1:3000/health
# Check SSL certificate
openssl s_client -connect chessgame.com:443 -servername chessgame.com
#!/bin/bash
# nginx-monitor.sh
echo "=== Nginx Status ==="
curl -s http://localhost/nginx_status
echo -e "\n=== Active Connections ==="
ss -tulpn | grep :80
ss -tulpn | grep :443
echo -e "\n=== Recent Errors ==="
tail -n 10 /var/log/nginx/error.log
echo -e "\n=== Top IPs by Request Count ==="
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
echo -e "\n=== Response Time Statistics ==="
awk '{print $NF}' /var/log/nginx/access.log | grep -E '^[0-9.]+$' | awk '{sum+=$1; count++} END {print "Average:", sum/count, "Count:", count}'
- Environment Configuration - Environment setup and variables
- Security Guide - Comprehensive security implementation
- Performance Guide - Application performance optimization
- Monitoring Guide - System monitoring and alerting