Skip to content

Instantly share code, notes, and snippets.

@serbaniuliuscezar
Created June 23, 2020 17:59
Show Gist options
  • Save serbaniuliuscezar/2b187ba1d85a4d85c5c892f3650810f9 to your computer and use it in GitHub Desktop.
Save serbaniuliuscezar/2b187ba1d85a4d85c5c892f3650810f9 to your computer and use it in GitHub Desktop.
# Run as a less privileged user for security reasons.
user www-data;
worker_processes auto;
pid /tmp/.nginx/nginx.pid;
events {
# Optimized to serve many clients with each thread, essential for Linux
use epoll;
# Accept as many connections as possible, may flood worker connections if set too low
multi_accept on;
# @link http://serverfault.com/questions/209014/how-can-i-observe-what-nginx-is-doing-to-solve-1024-worker-connections-are-n
worker_connections 2000;
}
# Maximum open file descriptors per process;
# should be > worker_connections
worker_rlimit_nofile 40000;
# Instructions on how to log upstream custom headers:
# https://stackoverflow.com/questions/12431496/nginx-read-custom-header-from-upstream-server
# Logging with Lua variables
# https://www.agilicus.com/logging-real-remote-address-with-nginx-and-lua/
http {
log_format main escape=json '{"Log Source": "NGINX", '
'"Client IP": "$remote_addr", '
'"Request": "$request", '
'"Status": "$status", '
'"Payload Size": "$body_bytes_sent", '
'"HTTP Host": "$host", '
'"HTTP Referer": "$http_referer", '
'"User Agent": "$http_user_agent", '
'"X-Request-ID": "$upstream_http_x_request_id", '
'"X-Debug-ID": "$upstream_http_x_debug_id", '
'"Response Time": "$upstream_response_time", '
'"Upstream Status": "$upstream_status", '
'"Upstream Response Length": "$upstream_response_length", '
'"Upstream Address": "$upstream_addr", '
'"X-Account-ID": "$http_x_account_id" }';
log_format debugging escape=json '{"Log Source": "NGINX", '
'"Client IP": "$remote_addr", '
'"Request": "$request", '
'"Status": "$status", '
'"Payload Size": "$body_bytes_sent", '
'"HTTP Host": "$host", '
'"HTTP Referer": "$http_referer", '
'"User Agent": "$http_user_agent", '
'"X-Request-ID": "$upstream_http_x_request_id", '
'"X-Debug-ID": "$upstream_http_x_debug_id", '
'"Response Time": "$upstream_response_time", '
'"Upstream Status": "$upstream_status", '
'"Upstream Response Length": "$upstream_response_length", '
'"Upstream Response Body": "$resp_body", '
'"Upstream Address": "$upstream_addr", '
'"X-Account-ID": "$http_x_account_id" }';
# Conditional map logging
# https://docs.nginx.com/nginx/admin-guide/monitoring/logging/
map $status $success_loggable {
~^[23] 1;
}
map $status $failure_loggable {
~^[45] 1;
}
# Log to as the sidecar fluentbit agents will forward the messages to their respective Splunk clusters
error_log /dev/stdout crit;
access_log /dev/stdout main buffer=32k flush=2s;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Do not display the nginx version
server_tokens off;
server_names_hash_bucket_size 64;
server_name_in_redirect off;
include /usr/local/openresty/nginx/conf/mime.types;
default_type application/octet-stream;
# @see https://blog.g3rt.nl/nginx-add_header-pitfall.html
# @see http://nginx.org/en/docs/http/ngx_http_headers_module.html
# @see https://securityheaders.io/
# @see https://scotthelme.co.uk/hardening-your-http-response-headers/#x-xss-protection
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "no-referrer";
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
gzip_min_length 256;
ignore_invalid_headers on;
client_header_timeout 240;
client_body_timeout 240;
# If a client stops responding, free up memory -- default is 60 seconds
# @link http://nginx.org/en/docs/http/ngx_http_core_module.html#send_timeout
send_timeout 30;
# @link http://nginx.org/en/docs/hash.html
types_hash_max_size 2048;
client_max_body_size 32k;
proxy_buffer_size 64k;
proxy_busy_buffers_size 64k;
proxy_buffers 9 8k;
# @link http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers
large_client_header_buffers 4 8k;
# @link http://nginx.org/en/docs/http/ngx_http_core_module.html#client_header_buffer_size
client_header_buffer_size 1k;
# if the request body size is more than the buffer size, then the entire (or partial) request body is written into a temporary file
# @link http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size
client_body_buffer_size 16k;
# Sets the maximum number of requests that can be served through one keep-alive connection.
# After the maximum number of requests are made, the connection is closed.
# @link http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests
keepalive_requests 10000;
# allow the server to close connection on non responding client, this will free up memory
# @link http://nginx.org/en/docs/http/ngx_http_core_module.html#reset_timedout_connection
reset_timedout_connection on;
client_body_temp_path /tmp/.nginx/client_body;
fastcgi_temp_path /tmp/.nginx/fastcgi_temp;
proxy_temp_path /tmp/.nginx/proxy_temp;
scgi_temp_path /tmp/.nginx/scgi_temp;
uwsgi_temp_path /tmp/.nginx/uwsgi_temp;
# Common headers and other parameters used for all reverse proxy endpoints
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 $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
#https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive
proxy_set_header Connection 'keep-alive';
proxy_cache_bypass $http_upgrade;
proxy_pass_header Server;
proxy_pass_request_headers on;
# By default the NGINX HTTP proxy directive uses HTTP 1.0 which does not support chunked content.
# So if Content-Length is empty, we immediately get no content body.
# http://serverfault.com/questions/482875/nginx-removes-content-length-header-for-chunked-content
# We need to explicitly use 1.1 for upstream connections.
proxy_http_version 1.1;
proxy_redirect off;
recursive_error_pages off;
# A secure NGINX configuration reference: https://blog.appcanary.com/2017/http-security-headers.html
# IP forwarding: https://calvin.me/forward-ip-addresses-when-using-nginx-proxy
server {
listen 4000;
charset utf-8;
port_in_redirect off;
underscores_in_headers on;
proxy_buffering off;
set_real_ip_from 10.0.0.0/8; # Trust the AWS ELBs IPs and use the real_ip_header header instead
set_real_ip_from 172.16.0.0/12; # Trust the AWS ELBs IPs and use the real_ip_header header instead
real_ip_header X-Forwarded-For;
real_ip_recursive on;
server_name_in_redirect off;
# Lua response body logging
# https://www.hardill.me.uk/wordpress/2018/03/14/logging-requests-and-response-with-nginx/
lua_need_request_body on;
set $response_body '';
set $resp_body '';
set $real_remote_client_ip '';
rewrite_by_lua_file lua/gzip.lua;
body_filter_by_lua_file lua/request_logger.lua;
# Read the client IP via Lua
set_by_lua_block $real_remote_client_ip {
if ngx.var.http_x_forwarded_for then
for r in ngx.var.http_x_forwarded_for:gmatch('([^,]+)') do
return r
end
end
return ngx.var.remote_addr
}
set $proxy_pass_url_api 127.0.0.1:3000;
# DNS servers for IP resolving
resolver 169.254.169.253 valid=300s;
resolver_timeout 300s;
server_name ""; # Don't worry if the "Host" HTTP Header is empty or not set
root /usr/local/openresty/nginx/html;
index index.html;
location /api {
access_log /dev/stdout main if=$success_loggable;
access_log /dev/stdout debugging if=$failure_loggable;
# Send the request to the local container process
proxy_pass http://$proxy_pass_url_api$uri$is_args$args;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment