# Frontend API server that: # 1. Acts as the HTTPS termination point. # 2. Authorizes HTTP requests with secret token header # and forwards to BDB backend. # 3. Forwards BDB WS requests to BDB backend. # 4. Does health check with LB. worker_processes 2; daemon off; user nobody nogroup; pid /tmp/nginx.pid; error_log /dev/stderr; events { # Each worker handles up to 512 connections. Increase this for heavy # workloads. worker_connections 512; accept_mutex on; use epoll; } http { access_log /dev/stdout combined buffer=16k flush=5s; # Allow 10 req/sec from the same IP address, and store the counters in a # `zone` or shared memory location tagged as 'one'. limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; # Enable logging when requests are being throttled. limit_req_log_level notice; # HTTP status code that is returned to the client; 429 is for TooManyRequests, # ref. RFC 6585 limit_req_status 429; # Limit requests from the same client, allow `burst` to 20 r/s, # `nodelay` or drop connection immediately in case it exceeds this # threshold. limit_req zone=one burst=20 nodelay; # `slowloris` attack mitigation settings. client_body_timeout 10s; client_header_timeout 10s; # Do not expose nginx data/version number in error response and header server_tokens off; # To prevent cross-site scripting add_header X-XSS-Protection "1; mode=block"; # DNS resolver to use for all the backend names specified in this configuration. resolver DNS_SERVER valid=30s ipv6=off; keepalive_timeout 60s; # The following map blocks enable lazy-binding to the backend at runtime, # rather than binding as soon as NGINX starts. map $remote_addr $bdb_backend { default PLANETMINT_BACKEND_HOST; } # Frontend server for the external clients; acts as HTTPS termination point. server { listen NODE_FRONTEND_PORT ssl; server_name "NODE_FQDN"; ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/cert.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; underscores_in_headers on; # Forward websockets directly to backend BDB. location /api/v1/streams/valid_transactions { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://$bdb_backend:PLANETMINT_WS_PORT; proxy_read_timeout 600s; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # Forward other URL paths as per business logic/use case to BDB or # OpenResty instance. location / { set $auth_check 1; #Flag to authorize POST requests proxy_ignore_client_abort on; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # max client request body size: avg transaction size. client_max_body_size 15k; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-Secret-Access-Token,User-Agent'; add_header 'Access-Control-Max-Age' 43200; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ( $http_x_secret_access_token != "SECRET_ACCESS_TOKEN" ) { set $auth_check 0; } if ($request_method = POST ) { set $auth_check "${auth_check}1"; } if ( $auth_check = "01" ) { return 403; } # No auth for GETs, forward directly to BDB. if ($request_method = GET) { proxy_pass http://$bdb_backend:PLANETMINT_API_PORT; } if ($request_method = POST ) { proxy_pass http://$bdb_backend:PLANETMINT_API_PORT; } # Only return this reponse if request_method is neither POST|GET|OPTIONS if ($request_method !~ ^(GET|OPTIONS|POST)$) { return 444; } } } # Frontend server for the load balancer to respond to health checks. server { listen HEALTH_CHECK_PORT; location = /health { return 200; } } # Frontend server for the external clients; returns a pretty error message # when an HTTP request is sent instead of HTTPS. server { listen 80; server_name "NODE_FQDN"; location / { add_header Upgrade "TLS/1.2, HTTP/1.1" always; default_type text/plain; return 426 'Consider using the HTTPS protocol next time!'; } } } # NGINX stream block for TCP and UDP proxies. stream { log_format bdb_log '[$time_iso8601] $realip_remote_addr $remote_addr ' '$proxy_protocol_addr $proxy_protocol_port ' '$protocol $status $session_time $bytes_sent ' '$bytes_received "$upstream_addr" "$upstream_bytes_sent" ' '"$upstream_bytes_received" "$upstream_connect_time" '; access_log /dev/stdout bdb_log buffer=16k flush=5s; # Define a zone 'two' of size 10 megabytes to store the counters # that hold number of TCP connections from a specific IP address. limit_conn_zone $binary_remote_addr zone=two:10m; # Enable logging when connections are being throttled. limit_conn_log_level notice; # Allow 256 connections from the same IP address. limit_conn two 256; # DNS resolver to use for all the backend names specified in this configuration. resolver DNS_SERVER valid=30s ipv6=off; # The following map blocks enable lazy-binding to the backend at runtime, # rather than binding as soon as NGINX starts. map $remote_addr $bdb_backend { default PLANETMINT_BACKEND_HOST; } # Server to forward connection to nginx instance hosting # tendermint node public key. server { listen TM_PUB_KEY_ACCESS_PORT; proxy_pass $bdb_backend:TM_PUB_KEY_ACCESS_PORT; } # Server to forward p2p connections to Tendermint instance. server { listen TM_P2P_PORT so_keepalive=3m:1m:5; preread_timeout 60s; tcp_nodelay on; proxy_pass $bdb_backend:TM_P2P_PORT; } }