# Default nginx configuration user REPLACE_SERVICE_USER; worker_processes 2; daemon on; error_log /data/logs/nginx/nginx.log warn; pid /run/nginx.pid; events { worker_connections 1024; } http { sendfile on; keepalive_timeout 65; gzip on; default_type "text/html"; include /etc/nginx/mime.types; access_log /data/logs/nginx/nginx.access.log; map $http_upgrade $connection_upgrade { default upgrade; '' close; } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Reverse-proxy header normalization # # Derive the real request scheme / host / port / prefix from upstream # headers, falling back to the local request if the header is absent. # Supports headers set by apache, haproxy, nginx, caddy, traefik, aws # elb/alb, gcp lb, cloudflare, fastly, akamai, varnish, kubernetes # ingress, and any RFC 7239 compliant proxy. # # Available downstream as $real_scheme, $real_host, $real_port, # $real_https, $real_prefix - and passed to fastcgi/PHP via # REQUEST_SCHEME, HTTP_HOST, SERVER_PORT, HTTPS, X-Forwarded-Prefix. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # X-Forwarded-Proto (or fall back to local scheme) map $http_x_forwarded_proto $real_scheme { default $http_x_forwarded_proto; "" $scheme; } # HTTPS flag for CGI/PHP, derived from real scheme map $real_scheme $real_https { https on; default ""; } # X-Forwarded-Host / Forwarded host= (or fall back to Host) map $http_x_forwarded_host $real_host { default $http_x_forwarded_host; "" $http_host; } # X-Forwarded-Port (or fall back to server port) map $http_x_forwarded_port $real_port { default $http_x_forwarded_port; "" $server_port; } # X-Forwarded-Prefix / X-Script-Name (path-based routing); empty if absent map $http_x_forwarded_prefix $real_prefix { default $http_x_forwarded_prefix; "" ""; } # Don't let nginx emit absolute redirects with the internal scheme/host; # send relative redirects that the browser resolves against its real URL. absolute_redirect off; port_in_redirect off; server_name_in_redirect off; # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Real client IP detection (apache, haproxy, nginx, caddy, traefik, # aws elb/alb, gcp lb, cloudflare, fastly, etc.) # # set_real_ip_from declares which upstream IPs are trusted; nginx then # walks X-Forwarded-For right-to-left, skipping any address inside a # trusted CIDR, until it finds the first untrusted address - that becomes # $remote_addr (also REMOTE_ADDR for fastcgi/PHP, and what shows up in # access logs and any allow/deny / rate-limit / geoip rules). # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # loopback set_real_ip_from 127.0.0.0/8; set_real_ip_from ::1/128; # RFC1918 private networks (covers internal proxy/LB, docker bridges, # kubernetes pod/service networks, vpn ranges, etc.) set_real_ip_from 10.0.0.0/8; set_real_ip_from 172.16.0.0/12; set_real_ip_from 192.168.0.0/16; # RFC6598 carrier-grade NAT (sometimes used by cloud LBs) set_real_ip_from 100.64.0.0/10; # Link-local set_real_ip_from 169.254.0.0/16; set_real_ip_from fe80::/10; # IPv6 unique-local set_real_ip_from fc00::/7; # Cloudflare IPv4 (https://www.cloudflare.com/ips-v4) set_real_ip_from 173.245.48.0/20; set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 108.162.192.0/18; set_real_ip_from 190.93.240.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 162.158.0.0/15; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 172.64.0.0/13; set_real_ip_from 131.0.72.0/22; # Cloudflare IPv6 (https://www.cloudflare.com/ips-v6) set_real_ip_from 2400:cb00::/32; set_real_ip_from 2606:4700::/32; set_real_ip_from 2803:f800::/32; set_real_ip_from 2405:b500::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2a06:98c0::/29; set_real_ip_from 2c0f:f248::/32; # X-Forwarded-For is the de-facto standard set by all major proxies and # CDNs. If you sit ONLY behind Cloudflare and want their authoritative # header, change this to: real_ip_header CF-Connecting-IP; real_ip_header X-Forwarded-For; real_ip_recursive on; server { listen REPLACE_SERVER_PORT; root REPLACE_SERVER_WWW_DIR; index index.html index.php index.cgi index.pl index.aspx awstats.pl index.unknown.php index.default.php index.txt index.json; proxy_intercept_errors off; 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" always; add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' *; frame-src 'self' *; object-src 'self'" always; location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location /health { default_type text/html; allow all; access_log off; return 200 'OK'; } location /health/text { default_type application/text; allow all; access_log off; return 200 'OK'; } location /health/json { default_type application/json; allow all; access_log off; return 200 '{"status":"OK"}'; } location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; if (!-f $document_root$fastcgi_script_name) { return 404; } fastcgi_index index.php; fastcgi_param HTTP_PROXY ""; fastcgi_param REDIRECT_STATUS 200; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; # Use the proxy-resolved values so $_SERVER reflects the actual # client-facing request, not the internal proxy hop. fastcgi_param SERVER_PORT $real_port; fastcgi_param SERVER_NAME $real_host; fastcgi_param HTTP_HOST $real_host; fastcgi_param REQUEST_SCHEME $real_scheme; fastcgi_param HTTPS $real_https if_not_empty; fastcgi_param QUERY_STRING $query_string; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # Pass the original forwarded headers through so apps that read # them directly (instead of REMOTE_ADDR/etc.) still work. fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for; fastcgi_param HTTP_X_FORWARDED_PROTO $real_scheme; fastcgi_param HTTP_X_FORWARDED_HOST $real_host; fastcgi_param HTTP_X_FORWARDED_PORT $real_port; fastcgi_param HTTP_X_FORWARDED_PREFIX $real_prefix; fastcgi_param HTTP_X_REAL_IP $remote_addr; fastcgi_pass 127.0.0.1:9000; } location /nginx_status { stub_status; } } }