In modern web infrastructure, application servers (such as Uvicorn, Node.js, or Puma) are engineered for executing business logic rather than serving static assets, terminating TLS handshakes, or managing rate limits. Positioning Nginx as an edge reverse proxy and SSL offloading gateway provides high availability, security hardening, and performance optimization.
By delegating TLS handshakes, HTTP/2 multiplexing, Gzip/Brotli compression, and static asset caching to Nginx, backend application workers operate with significantly reduced CPU overhead. In this technical guide, we configure a production Nginx gateway featuring TLS 1.3 offloading, upstream load balancing, WebSocket proxying, and security headers.
1. The Role of TLS/SSL Offloading
Cryptographic handshakes (RSA/ECDSA key exchanges and AES-GCM symmetric decryption) consume substantial CPU cycles. In an un-proxied setup, every application worker thread must perform cryptographic decryption for incoming HTTPS packets.
With SSL Offloading (TLS Termination), Nginx handles public HTTPS encryption on port 443, validates certificates, and forwards plain HTTP traffic over isolated, private virtual networks (e.g. http://10.0.1.50:8000) to backend application servers. This concentrates cryptographic processing into Nginx's highly optimized C event-loop workers.
2. Production Nginx Configuration Architecture
Below is a hardened production nginx.conf configuration for riddletech.co.ke, enforcing HTTP/2, TLS 1.3, OCSP stapling, security headers, and upstream load balancing:
# Global worker processes matching CPU cores
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 8192;
use epoll;
multi_accept on;
}
http {
include mime.types;
default_type application/octet-stream;
# Performance Tuning Options
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# Brotli & Gzip Compression
gzip on;
gzip_comp_level 5;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# Rate Limiting Zones (Prevents DDoS and brute-force attacks)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
# Upstream Backend Server Cluster
upstream backend_nodes {
least_conn; # Route traffic to least connected worker
server 10.0.1.10:8000 max_fails=3 fail_timeout=10s;
server 10.0.1.11:8000 max_fails=3 fail_timeout=10s;
keepalive 32; # Keep-alive idle connections to upstream
}
# Redirect HTTP to HTTPS automatically
server {
listen 80;
listen [::]:80;
server_name riddletech.co.ke www.riddletech.co.ke;
return 301 https://$host$request_uri;
}
# Main HTTPS Gateway Server Block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name riddletech.co.ke www.riddletech.co.ke;
# SSL Certificate Paths
ssl_certificate /etc/letsencrypt/live/riddletech.co.ke/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/riddletech.co.ke/privkey.pem;
# Hardened TLS Protocols & Ciphers (TLS 1.2 and TLS 1.3 only)
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_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling for fast TLS handshakes
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
# Security Headers (OWASP Recommendations)
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Root Static Directory
root /var/www/riddletech.web;
index index.html;
# Reverse Proxy Location for Dynamic API Traffic
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend_nodes;
proxy_http_version 1.1;
# Forward real client connection metadata
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;
# Timeouts
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
# WebSocket Proxy Support
location /ws/ {
proxy_pass http://backend_nodes;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
}
}
3. Configuring WebSocket Upgrades
Unlike standard HTTP requests that terminate after receiving a response, WebSocket connections maintain persistent full-duplex TCP streams. To proxy WebSockets through Nginx without premature disconnection, explicitly set the Upgrade and Connection HTTP headers as shown in the location block above.
4. Upstream Health Checks & Load Balancing
Nginx provides built-in passive health checks for upstream server pools using the max_fails and fail_timeout directives. If an upstream app node fails 3 consecutive health checks within 10 seconds, Nginx automatically ejects that server node from the pool until it recovers, eliminating single points of failure.
Conclusion
Configuring Nginx as an edge reverse proxy and TLS offloading gateway delivers dramatic performance, security, and stability benefits. With TLS 1.3 enabled, OCSP stapling active, and robust upstream health checks configured, backend services can scale seamlessly under heavy production workloads.