- Modify
nginx.conf
into /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024; # Adjusted for higher capacity
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 64;
server_name_in_redirect off;
client_max_body_size 512M;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Updated SSL Settings
ssl_protocols TLSv1.2 TLSv1.3; # Dropping older protocols
ssl_prefer_server_ciphers on;
# Logging Settings
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Connection header for WebSocket reverse proxy
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
map $remote_addr $proxy_forwarded_elem {
# IPv4 addresses can be sent as-is
~^[0-9.]+$ "for=$remote_addr";
# IPv6 addresses need to be bracketed and quoted
~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";
# Unix domain socket names cannot be represented in RFC 7239 syntax
default "for=unknown";
}
map $http_forwarded $proxy_add_forwarded {
# If the incoming Forwarded header is syntactically valid, append to it
"~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
# Otherwise, replace it
default "$proxy_forwarded_elem";
}
# Recommended 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 "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self';" always;
}
- Add
web.conf
into /etc/nginx/conf.d
folder
# Enhanced SSL Configuration
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Rate Limiting
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
# gzip Compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
proxy_cache_path /var/cache/frontend levels=1:2 keys_zone=cache:25m max_size=1g inactive=60m use_temp_path=off;
map $sent_http_content_type $expires {
"text/html" 10m; # Shorter expiration for HTML
"text/css" 1d; # Daily update for CSS
"application/javascript" 1d; # Daily update for JavaScript
default 1y; # Long-term caching for other types
}
upstream backend {
zone upstreams 64K;
server 127.0.0.1:3000;
keepalive 50;
}
server {
listen 80;
listen 443 ssl http2;
server_name example.com www.example.com;
# Redirect HTTP to HTTPS
if ( $scheme = "http" ) {
return 301 https://$host$request_uri;
}
# SSL Certificates
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Security Headers
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 Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
add_header Permissions-Policy "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Cache-Status $upstream_cache_status;
location /api/ {
expires off;
proxy_pass http://backend/api/;
proxy_cache off;
}
proxy_redirect off;
proxy_http_version 1.1;
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 "Connection" "";
# Proxy timeout
proxy_send_timeout 10m;
proxy_read_timeout 10m;
proxy_connect_timeout 10m;
location / {
expires $expires;
proxy_pass http://backend/;
# Proxy cache
proxy_cache cache;
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 1m;
# Cache bypass conditions
proxy_cache_bypass $arg_purgecache;
proxy_cache_bypass $http_x_purge_cache;
proxy_cache_bypass $cookie_purgecache;
# Rate Limiting
limit_req zone=mylimit;
}
access_log off;
error_log /var/log/nginx/example.com-error.log error;
# ACME-challenge
location ^~ /.well-known/acme-challenge/ {
root /var/www/_letsencrypt;
}
# Deny access to hidden files
location ~ /\.(?!well-known).* {
deny all;
}
# Custom Error Pages
# error_page 404 /custom_404.html;
# error_page 500 502 503 504 /custom_50x.html;
# location = /custom_404.html {
# root /usr/share/nginx/html;
# internal;
# }
# location = /custom_50x.html {
# root /usr/share/nginx/html;
# internal;
# }
}