# Security-conscious rl-nginx configuration patterns. # # The tenant and API key are deliberately non-working placeholders. Replace # them before running nginx -t. The local resolver must also match the # deployment's trusted DNS path. events {} http { resolver 127.0.0.53 valid=30s ipv6=off; resolver_timeout 2s; # Convert client-selected paths and methods to a finite operator-controlled # vocabulary. Raw URI, argument, header, and cookie values are not identities. map $uri $rl_route_class { default other; ~^/api/orders(?:/|$) orders; ~^/api/search(?:/|$) search; } map $request_method $rl_method_class { default other; GET read; POST write; } # Every output is a valid bounded rate. Do not let a request argument or # cookie select an authenticated service plan. map "$rl_route_class:$rl_method_class" $rl_api_rate { default 10r/s; orders:read 100r/s; orders:write 20r/s; search:read 30r/s; } ratelimitly_dns_srv tenant.example.invalid; ratelimitly_auth_key rl-aes1REPLACE_WITH_YOUR_KEY; ratelimitly_policy standard unit=50ms; # Set the availability/security policy explicitly. See docs/configuration.md. ratelimitly_fail close; ratelimitly_debug off; # All components before the final address come from finite maps. Textual # $remote_addr is last, so IPv6 ':' characters cannot alter field boundaries. # Configure real-IP/proxy-protocol trust before relying on this identity. ratelimitly_zone api_per_ip "bucket=v1|scope=api|route=$rl_route_class|method=$rl_method_class|ip=$remote_addr" rate=$rl_api_rate; # Keep service identity fixed or map it to a finite set. Raw $host/$uri and # user-supplied values fragment latency history and create high cardinality. ratelimitly_tracker api_latency_tracker "service=v1|service=public-api" ttl=30s max_samples=128 buffer_size=32 min_sample_threshold=8; ratelimitly_guard api_latency tracker=api_latency_tracker threshold=100ms; server { listen 8080; server_name api.example.invalid; location /api/ { # Labels are transmitted. Use only bounded, non-sensitive values. ratelimitly_label "route=$rl_route_class|method=$rl_method_class"; ratelimitly zone=api_per_ip guard=api_latency; # Reporting is explicit and independent from use of the guard. ratelimitly_report api_latency_tracker; proxy_pass http://127.0.0.1:9000; } } }