-
-
Save hazho/a17e3a29ff68e5c809c57b757585e33d to your computer and use it in GitHub Desktop.
NGINX:v1.17.0 With modSecurity:v3.0.0 and Brotli Custom Docker Image for Production
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
worker_processes auto; | |
worker_rlimit_core 500M; | |
events { | |
accept_mutex off; | |
worker_connections 1024; | |
multi_accept on; | |
use epoll; | |
} | |
http { | |
# MIME | |
# include mime.types; | |
default_type application/octet-stream; | |
log_format compression '$remote_addr - $remote_user [$time_local] ' | |
'"$request" $status $body_bytes_sent ' | |
'"$http_referer" "$http_user_agent" "$gzip_ratio"'; | |
# Conection Timeouts | |
client_body_timeout 12; | |
client_header_timeout 12; | |
keepalive_timeout 15; | |
send_timeout 10; | |
access_log on; | |
sendfile on; | |
tcp_nopush on; | |
tcp_nodelay on; | |
server_tokens off; | |
log_not_found off; | |
types_hash_max_size 2048; | |
# Encoding with gzip | |
gzip on; | |
gzip_disable "msie6"; | |
gzip_vary on; | |
gunzip on; | |
gzip_proxied any; | |
gzip_comp_level 9; | |
gzip_buffers 16 8k; | |
gzip_http_version 1.1; | |
gzip_min_length 1000; | |
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript; | |
# brotli | |
brotli on; | |
brotli_comp_level 6; | |
brotli_static on; | |
brotli_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript image/png image/svg+xml image/x-icon image/jpeg font/woff font/woff2; | |
# Rate Limiting based on zone for 10m (1,60,000 stored IP addresses) and for each unique IP 30 requests per second | |
limit_req_zone $binary_remote_addr zone=ratelimit:20m rate=50r/s; | |
# include /etc/nginx/conf.d/*; | |
upstream backend { | |
server backend:8080; | |
} | |
upstream ui { | |
server ui:4000; | |
} | |
server { | |
listen 80 default_server; | |
server_name _; | |
return 301 https://$host$request_uri; | |
} | |
map $status $loggable { | |
~^[23] 0; | |
default 1; | |
} | |
access_log /var/log/nginx/access.log combined if=$loggable; | |
error_log /var/log/nginx/error.log warn; | |
server { | |
listen 443 ssl http2; | |
server_name example.com; | |
underscores_in_headers on; | |
## Enable ModSecurity | |
modsecurity on; | |
# Buffers | |
client_body_buffer_size 10K; | |
client_header_buffer_size 1k; | |
client_max_body_size 8m; | |
large_client_header_buffers 4 32k; | |
ssl on; | |
ssl_certificate /root/certs/example.crt; | |
ssl_certificate_key /root/certs/example.key; | |
ssl_session_cache shared:SSL:5m; # holds approx 4000 sessions | |
ssl_session_timeout 24h; # 1 hour during which sessions can be re-used. | |
ssl_session_tickets off; | |
ssl_protocols TLSv1.2 TLSv1.3; | |
ssl_buffer_size 8k; | |
# security headers | |
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 Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; | |
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; | |
if ($request_method = OPTIONS ) { | |
add_header Access-Control-Allow-Origin "*"; | |
add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,PUT,DELETE,PATCH"; | |
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; | |
add_header Access-Control-Allow-Credentials "true"; | |
add_header 'Content-Type' 'text/plain; charset=utf-8'; | |
add_header 'Access-Control-Expose-Headers' 'Content- Length,Content-Range'; | |
add_header 'Access-Control-Max-Age' 1728000; | |
add_header Content-Length 0; | |
add_header Cache-Control 'max-age=0'; | |
return 204; | |
} | |
location /api/v1/ { | |
limit_req zone=ratelimit burst=30 nodelay; | |
limit_req_log_level warn; | |
proxy_pass http://backend; | |
proxy_redirect off; | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $remote_addr; | |
proxy_set_header X-Forwarded-Host $server_name; | |
proxy_buffering off; | |
proxy_buffer_size 128k; | |
proxy_buffers 100 128k; | |
add_header X-Frame-Options DENY; | |
add_header X-Content-Type-Options nosniff; | |
} | |
location / { | |
proxy_pass http://ui; | |
proxy_redirect off; | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $remote_addr; | |
proxy_set_header X-Forwarded-Host $server_name; | |
location ~* \.(html|css|jpg|gif|ico|js|png|woff|woff2)$ { | |
proxy_cache_key $host$uri$is_args$args; | |
proxy_cache_valid 200 301 302 30m; | |
expires 30m; | |
proxy_pass http://ui; | |
} | |
add_header X-Frame-Options DENY; | |
add_header X-Content-Type-Options nosniff; | |
expires 365d; | |
gzip_static on; | |
sendfile on; | |
gzip on; | |
gzip_disable "msie6"; | |
gzip_vary on; | |
gunzip on; | |
gzip_comp_level 9; | |
gzip_buffers 16 8k; | |
gzip_http_version 1.1; | |
gzip_min_length 1000; | |
gzip_proxied expired no-cache no-store private auth; | |
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript image/png image/svg+xml image/x-icon image/jpeg font/woff font/woff2; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment