Securing MapProxy with Nginx and ModSecurity
Securing a production-grade MapProxy deployment requires a layered defense strategy that aligns reverse proxy routing, web application firewall inspection, and geospatial service validation. When integrating MapProxy into an enterprise geospatial portal, the primary objective is to enforce strict ingress controls while preserving the low-latency tile delivery and dynamic WMS/WMTS transformations that downstream clients expect. This operational guide details the precise configuration, debugging workflows, and scaling considerations required to harden the stack using Nginx and ModSecurity. The architectural decisions outlined here directly support the broader Core Portal Architecture & Security Boundaries framework, ensuring that tile caching layers remain isolated from origin data stores and that external traffic is sanitized before reaching the MapProxy application process.
The request inspection pipeline below shows how Nginx and ModSecurity sanitize OGC traffic at the edge before it ever reaches the MapProxy worker pool.
flowchart LR
Client["Client"] --> NX
subgraph EdgeLayer [Nginx edge]
NX["Nginx — TLS, rate limit, buffering"]
MS["ModSecurity — CRS + OGC rule tuning"]
end
NX --> MS
MS -->|"clean OGC request"| MP["MapProxy backend"]
MS -->|"blocked"| Deny["403 + modsec_audit.log"]
MP --> Cache[("Tile cache / upstream WMS")]
Nginx Ingress & Upstream Orchestration
Nginx serves as the primary ingress controller and traffic orchestrator for MapProxy. A standard deployment must account for the stateless nature of tile requests alongside the stateful requirements of OGC metadata and capability documents. The upstream configuration should utilize keepalive connections to prevent socket exhaustion during high-concurrency tile storms. Buffering directives must be carefully tuned; MapProxy frequently streams large raster payloads or complex WMS responses, and disabling proxy_buffering for specific endpoints can prevent memory thrashing on the reverse proxy. However, leaving buffering enabled globally is recommended for standard tile requests to absorb backend latency spikes. For comprehensive directive references, consult the official Nginx Proxy Module Documentation.
upstream mapproxy_backend {
server 127.0.0.1:8080;
keepalive 64;
}
server {
listen 443 ssl http2;
server_name tiles.example.gov;
# Global buffering for tile delivery
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# Header injection for audit logging and cache key generation
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
location /tiles/ {
proxy_pass http://mapproxy_backend/tiles/;
}
location /wms/ {
proxy_pass http://mapproxy_backend/wms/;
# Disable buffering for streaming WMS/GetFeatureInfo
proxy_buffering off;
proxy_read_timeout 300s;
}
location /wmts/ {
proxy_pass http://mapproxy_backend/wmts/;
}
}
Traffic Shaping & Edge Case Mitigation
Edge cases frequently emerge when clients submit malformed BBOX parameters or exceed coordinate precision limits. Nginx should enforce strict URI length limits via large_client_header_buffers and client_max_body_size to reject oversized GetFeatureInfo payloads before they consume MapProxy worker threads. Implementing a dedicated rate-limiting zone using limit_req_zone based on $binary_remote_addr mitigates cache stampedes and prevents abusive scraping of high-resolution tile grids. For scaling deployments, the proxy_next_upstream directive should be configured to retry only on error and timeout, avoiding silent retries on http_500 or http_404 which can mask underlying MapProxy configuration errors.
# Rate limiting zone
limit_req_zone $binary_remote_addr zone=mapproxy_req:10m rate=30r/s;
server {
limit_req zone=mapproxy_req burst=60 nodelay;
limit_req_status 429;
large_client_header_buffers 4 16k;
client_max_body_size 10m;
location / {
proxy_next_upstream error timeout;
proxy_next_upstream_tries 1;
proxy_connect_timeout 5s;
# ... existing proxy directives
}
}
ModSecurity Calibration & OGC Rule Tuning
ModSecurity integration introduces a critical inspection layer that must be calibrated to avoid breaking legitimate OGC traffic. The OWASP Core Rule Set provides a strong baseline, but geospatial services routinely trigger false positives due to XML namespaces, JSON coordinate arrays, and URL-encoded query strings. To align with the Security Boundary Mapping for OGC Services, administrators must implement targeted rule exclusions for WMS/WMTS endpoints while maintaining strict SQLi and XSS protections for authentication and metadata paths.
# ModSecurity v3 configuration for Nginx
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
# Disable CRS rule 941100 (XSS) for WMS GetMap requests due to coordinate arrays
SecRule REQUEST_URI "@beginsWith /wms/" \
"id:10001,phase:2,pass,nolog,ctl:ruleRemoveById=941100"
# Disable CRS rule 942100 (SQLi) for BBOX parameters containing commas/decimals
SecRule ARGS:BBOX "@rx ^[\d\.\-,]+$" \
"id:10002,phase:2,pass,nolog,ctl:ruleRemoveById=942100"
# Allow XML namespaces in GetFeatureInfo responses
SecRule RESPONSE_CONTENT_TYPE "@contains xml" \
"id:10003,phase:3,pass,nolog,ctl:ruleRemoveById=941160"
Production Troubleshooting & Validation Workflows
When validating the hardened stack, platform engineers should follow a systematic debugging workflow. Begin by verifying Nginx access and error logs with $request_time and $upstream_response_time to identify buffering bottlenecks. If ModSecurity blocks legitimate tile requests, inspect the audit log (/var/log/modsec_audit.log) and correlate the rule_id with the offending query parameter. Use curl with verbose output to simulate OGC requests and verify header propagation:
curl -v "https://tiles.example.gov/wms/?SERVICE=WMS&REQUEST=GetCapabilities" \
-H "X-Debug-Mode: true"
For persistent 502 Bad Gateway errors during high-load scenarios, verify that the MapProxy gunicorn or uwsgi worker pool is not saturated. Adjust proxy_read_timeout and proxy_connect_timeout incrementally, and monitor upstream connection states via ss -tunap. Ensure that proxy_buffer_size is never smaller than the largest expected WMS capability document header. Validate coordinate parsing against the OGC Web Map Service Specification to confirm that edge-case geometries are correctly normalized before reaching the application layer.
Scaling & Operational Maintenance
Production scaling requires continuous monitoring of cache hit ratios and upstream latency. Implement active health checks at the load balancer level to route around degraded MapProxy instances. Regularly audit ModSecurity rule exclusions to prevent drift, and rotate Nginx logs using logrotate to avoid disk exhaustion. By maintaining strict ingress boundaries and validating OGC payloads at the edge, geospatial platforms can sustain high-throughput tile delivery without compromising enterprise security postures.