Sistema de Apoio ao Processo Legislativo
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

159 lines
6.5 KiB

upstream sapl_server {
server unix:/var/interlegis/sapl/run/gunicorn.sock fail_timeout=0;
}
# Reuse X-Request-ID from ingress if present; otherwise generate one.
map $http_x_request_id $req_id {
default $http_x_request_id;
"" $request_id;
}
server {
listen 80;
server_name sapl.prod;
client_max_body_size 4G;
# ----------------------------------------------------------------
# Block known scraper ASNs (datacenter traffic) — zero Python cost.
# ----------------------------------------------------------------
if ($bot_asn = 1) {
return 429 "Too Many Requests";
}
# ----------------------------------------------------------------
# Block known bots by User-Agent — zero Python cost.
# ----------------------------------------------------------------
if ($bot_ua_blocked = 1) {
return 429 "Too Many Requests";
}
# ----------------------------------------------------------------
# robots.txt served directly by nginx.
# ----------------------------------------------------------------
location = /robots.txt {
alias /var/interlegis/sapl/collected_static/robots.txt;
}
# ----------------------------------------------------------------
# Static files — no rate limiting, no proxy.
# ----------------------------------------------------------------
location /static/ {
alias /var/interlegis/sapl/collected_static/;
}
# ----------------------------------------------------------------
# Media files — FIX: add ETags and Cache-Control headers.
# sendfile on + etag on converts repeat bot requests to 304s.
# ----------------------------------------------------------------
location /media/ {
alias /var/interlegis/sapl/media/;
sendfile on;
etag on;
add_header Cache-Control "public, max-age=86400, stale-while-revalidate=3600";
add_header X-Robots-Tag "noindex" always;
}
# Private documents — X-Accel-Redirect after auth check in Django.
location /media/documentos_privados/ {
internal;
alias /var/interlegis/sapl/media/documentos_privados/;
}
# ----------------------------------------------------------------
# /relatorios/ — heaviest endpoint (PDF generation).
# Tighter rate limit; extended timeout for uncached generation.
# ----------------------------------------------------------------
location /relatorios/ {
limit_req zone=sapl_heavy burst=5 nodelay;
limit_req_status 429;
proxy_read_timeout 180s;
proxy_send_timeout 180s;
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sapl_server;
}
# ----------------------------------------------------------------
# Upload endpoints — nginx buffers the full upload before forwarding.
# Protects workers from slow municipal-link clients uploading 150 MB.
# ----------------------------------------------------------------
location ~* ^/(protocoloadm/criar-protocolo|materia/.*upload|norma/.*upload) {
proxy_request_buffering on;
proxy_read_timeout 180s;
proxy_send_timeout 180s;
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sapl_server;
}
# ----------------------------------------------------------------
# /api/ — rate limited, CORS maintained from original config.
# ----------------------------------------------------------------
location /api/ {
limit_req zone=sapl_general burst=30 nodelay;
limit_req_status 429;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, HEAD, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Access-Control-Allow-Origin,XMLHttpRequest,Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With';
add_header 'Access-Control-Expose-Headers' 'Access-Control-Allow-Origin,XMLHttpRequest,Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, HEAD, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sapl_server;
}
# ----------------------------------------------------------------
# General traffic — moderate rate limit.
# ----------------------------------------------------------------
location / {
limit_req zone=sapl_general burst=20 nodelay;
limit_req_status 429;
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sapl_server;
}
error_page 429 /429.html;
location = /429.html {
root /var/interlegis/sapl/sapl/static/;
internal;
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/interlegis/sapl/sapl/static/;
internal;
}
}