OpenResty Web Application Firewall
High-performance web platform with Lua scripting and ModSecurity WAF.
Overview
OpenResty is a high-performance web platform built on Nginx that extends the server with LuaJIT scripting capabilities, enabling developers to write complex web application logic directly within the web server. Originally created by Yichun Zhang at CloudFlare, OpenResty transforms Nginx from a simple reverse proxy into a programmable application server capable of handling complex routing, authentication, rate limiting, and data processing tasks at wire speed. The platform has become the backbone for many high-traffic applications requiring sub-millisecond response times and sophisticated request handling logic.
This stack combines OpenResty's programmable web server with OWASP ModSecurity's industry-standard Web Application Firewall, creating a powerful security-first web platform. ModSecurity provides real-time application attack detection and prevention using the OWASP Core Rule Set, while OpenResty's Lua scripting enables custom security logic, dynamic routing, and request transformation. The integration allows security policies to be implemented both at the WAF layer for standard threats and in Lua for application-specific security requirements, creating multiple layers of protection.
This combination is ideal for organizations requiring enterprise-grade web application security with the flexibility to implement custom business logic at the edge. Security teams benefit from ModSecurity's comprehensive attack detection, while developers can leverage OpenResty's Lua environment to build sophisticated API gateways, implement OAuth flows, perform real-time data enrichment, and create custom caching strategies. The included Prometheus and Grafana stack provides deep visibility into both security events and application performance metrics.
Key Features
- LuaJIT-powered request processing enabling sub-millisecond custom logic execution within Nginx
- OWASP ModSecurity Core Rule Set with configurable paranoia levels for SQL injection, XSS, and attack prevention
- Real-time security metrics collection with ModSecurity audit logs exported to Prometheus
- Lua-based dynamic routing and request transformation without external application servers
- Integrated anomaly scoring system with configurable inbound/outbound thresholds for adaptive security
- Custom Lua script hot-reloading for zero-downtime security policy and business logic updates
- TLS termination with certificate management and HTTP/2 support through OpenResty
- Grafana dashboards for WAF attack visualization and OpenResty performance monitoring
Common Use Cases
- 1API gateway with custom authentication and rate limiting for microservices architectures
- 2High-traffic e-commerce platforms requiring real-time fraud detection and request filtering
- 3SaaS applications needing tenant-specific routing and security policies implemented in Lua
- 4Financial services requiring PCI DSS compliance with comprehensive web application protection
- 5Gaming platforms implementing custom session management and anti-bot protection logic
- 6Healthcare applications requiring HIPAA-compliant request logging and data sanitization
- 7Edge computing deployments where business logic execution must happen closest to users
Prerequisites
- Docker Engine 20.10+ with at least 2GB RAM available for OpenResty and ModSecurity processing
- Basic understanding of Nginx configuration syntax and HTTP request/response flow
- Lua programming knowledge for implementing custom security and business logic in OpenResty
- Familiarity with OWASP security principles and ModSecurity rule syntax for WAF customization
- Ports 80, 443, 3000, and 9090 available on the host system for web traffic and monitoring
- SSL/TLS certificates placed in ./certs directory for HTTPS termination if required
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 openresty: 3 image: openresty/openresty:alpine4 ports: 5 - "80:80"6 - "443:443"7 volumes: 8 - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro9 - ./lua:/usr/local/openresty/nginx/lua:ro10 - ./certs:/etc/nginx/certs:ro11 - openresty_logs:/usr/local/openresty/nginx/logs12 networks: 13 - openresty-net14 restart: unless-stopped1516 modsecurity: 17 image: owasp/modsecurity-crs:nginx18 environment: 19 - PARANOIA=120 - ANOMALY_INBOUND=521 - ANOMALY_OUTBOUND=422 - BACKEND=http://app:808023 volumes: 24 - ./modsec-rules:/etc/modsecurity.d/owasp-crs/rules:ro25 networks: 26 - openresty-net27 restart: unless-stopped2829 app: 30 image: traefik/whoami:latest31 networks: 32 - openresty-net33 restart: unless-stopped3435 prometheus: 36 image: prom/prometheus:latest37 ports: 38 - "9090:9090"39 volumes: 40 - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro41 - prometheus_data:/prometheus42 networks: 43 - openresty-net44 restart: unless-stopped4546 grafana: 47 image: grafana/grafana:latest48 ports: 49 - "3000:3000"50 environment: 51 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}52 volumes: 53 - grafana_data:/var/lib/grafana54 depends_on: 55 - prometheus56 networks: 57 - openresty-net58 restart: unless-stopped5960volumes: 61 openresty_logs: 62 prometheus_data: 63 grafana_data: 6465networks: 66 openresty-net: 67 driver: bridge.env Template
.env
1# Grafana2GRAFANA_PASSWORD=secure_grafana_password34# ModSecurity5PARANOIA_LEVEL=1Usage Notes
- 1OpenResty at http://localhost
- 2ModSecurity WAF protection enabled
- 3Write custom Lua scripts in /lua folder
- 4Grafana at http://localhost:3000
Individual Services(5 services)
Copy individual services to mix and match with your existing compose files.
openresty
openresty:
image: openresty/openresty:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro
- ./lua:/usr/local/openresty/nginx/lua:ro
- ./certs:/etc/nginx/certs:ro
- openresty_logs:/usr/local/openresty/nginx/logs
networks:
- openresty-net
restart: unless-stopped
modsecurity
modsecurity:
image: owasp/modsecurity-crs:nginx
environment:
- PARANOIA=1
- ANOMALY_INBOUND=5
- ANOMALY_OUTBOUND=4
- BACKEND=http://app:8080
volumes:
- ./modsec-rules:/etc/modsecurity.d/owasp-crs/rules:ro
networks:
- openresty-net
restart: unless-stopped
app
app:
image: traefik/whoami:latest
networks:
- openresty-net
restart: unless-stopped
prometheus
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
networks:
- openresty-net
restart: unless-stopped
grafana
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
networks:
- openresty-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 openresty:5 image: openresty/openresty:alpine6 ports:7 - "80:80"8 - "443:443"9 volumes:10 - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro11 - ./lua:/usr/local/openresty/nginx/lua:ro12 - ./certs:/etc/nginx/certs:ro13 - openresty_logs:/usr/local/openresty/nginx/logs14 networks:15 - openresty-net16 restart: unless-stopped1718 modsecurity:19 image: owasp/modsecurity-crs:nginx20 environment:21 - PARANOIA=122 - ANOMALY_INBOUND=523 - ANOMALY_OUTBOUND=424 - BACKEND=http://app:808025 volumes:26 - ./modsec-rules:/etc/modsecurity.d/owasp-crs/rules:ro27 networks:28 - openresty-net29 restart: unless-stopped3031 app:32 image: traefik/whoami:latest33 networks:34 - openresty-net35 restart: unless-stopped3637 prometheus:38 image: prom/prometheus:latest39 ports:40 - "9090:9090"41 volumes:42 - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro43 - prometheus_data:/prometheus44 networks:45 - openresty-net46 restart: unless-stopped4748 grafana:49 image: grafana/grafana:latest50 ports:51 - "3000:3000"52 environment:53 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}54 volumes:55 - grafana_data:/var/lib/grafana56 depends_on:57 - prometheus58 networks:59 - openresty-net60 restart: unless-stopped6162volumes:63 openresty_logs:64 prometheus_data:65 grafana_data:6667networks:68 openresty-net:69 driver: bridge70EOF7172# 2. Create the .env file73cat > .env << 'EOF'74# Grafana75GRAFANA_PASSWORD=secure_grafana_password7677# ModSecurity78PARANOIA_LEVEL=179EOF8081# 3. Start the services82docker compose up -d8384# 4. View logs85docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/openresty-waf/run | bashTroubleshooting
- ModSecurity blocks legitimate requests: Reduce PARANOIA level from 1 to 0 or adjust ANOMALY_INBOUND threshold above 5
- OpenResty Lua scripts fail to load: Check file permissions in ./lua directory and ensure files are readable by container user
- High memory usage in OpenResty: Tune lua_shared_dict sizes in nginx.conf and implement proper Lua garbage collection
- ModSecurity rules not updating: Restart the modsecurity container and verify custom rules in ./modsec-rules are valid
- Prometheus missing ModSecurity metrics: Enable mod_security audit logging and configure nginx-lua-prometheus module
- Grafana dashboards show no data: Verify Prometheus is scraping OpenResty metrics endpoint and ModSecurity exporter is running
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
openrestymodsecurityprometheusgrafana
Tags
#openresty#nginx#waf#lua#security
Category
Web Servers & Reverse ProxiesAd Space
Shortcuts: C CopyF FavoriteD Download