Edward Ribeiro
eaf4a8405a
Phase 0 hardening: nginx GeoIP2, rate limits, Gunicorn tuning, N+1 fix
- nginx: sendfile on, tcp_nopush, reduced keepalive/proxy timeouts
- nginx: GeoIP2 ASN-based bot blocking (cloud providers + known scrapers)
- nginx: UA blocklist (GPTBot, ClaudeBot, Chrome/98.0.4758 impersonator, etc.)
- nginx: rate-limit zones (30r/m general, 10r/m heavy/relatorios), 429/500 error pages
- nginx: proper ETags + Cache-Control on /media/ to stop 30GB logo re-transfers
- Dockerfile: install libnginx-mod-http-geoip2; download GeoLite2-ASN.mmdb via
BuildKit secret (key never baked into image layers); ARG GEOIP_CACHE_BUST for
forced re-download without --no-cache
- Gunicorn: workers 3->2, threads 8->4, timeout 300->120, max_memory 300->400MB
- Django: FILE_UPLOAD_MAX_MEMORY_SIZE=2MB, FILE_UPLOAD_TEMP_DIR for large uploads
- relatorios/views.py: fix N+1 in get_etiqueta_protocolos with bulk-fetch
MateriaLegislativa + DocumentoAdministrativo using select_related + dict lookups
- Add robots.txt, 429.html, 500.html static pages
- docker-compose.yaml: use sapl:local for local dev
- docker/README.md: build instructions with MAXMIND_LICENSE_KEY
- rate-limiter-v2.md: canonical planning document (Architecture through Phase 5)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 weeks ago