docker.recipes

OpenResty Web Application Firewall

advanced

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:alpine
4 ports:
5 - "80:80"
6 - "443:443"
7 volumes:
8 - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro
9 - ./lua:/usr/local/openresty/nginx/lua:ro
10 - ./certs:/etc/nginx/certs:ro
11 - openresty_logs:/usr/local/openresty/nginx/logs
12 networks:
13 - openresty-net
14 restart: unless-stopped
15
16 modsecurity:
17 image: owasp/modsecurity-crs:nginx
18 environment:
19 - PARANOIA=1
20 - ANOMALY_INBOUND=5
21 - ANOMALY_OUTBOUND=4
22 - BACKEND=http://app:8080
23 volumes:
24 - ./modsec-rules:/etc/modsecurity.d/owasp-crs/rules:ro
25 networks:
26 - openresty-net
27 restart: unless-stopped
28
29 app:
30 image: traefik/whoami:latest
31 networks:
32 - openresty-net
33 restart: unless-stopped
34
35 prometheus:
36 image: prom/prometheus:latest
37 ports:
38 - "9090:9090"
39 volumes:
40 - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
41 - prometheus_data:/prometheus
42 networks:
43 - openresty-net
44 restart: unless-stopped
45
46 grafana:
47 image: grafana/grafana:latest
48 ports:
49 - "3000:3000"
50 environment:
51 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
52 volumes:
53 - grafana_data:/var/lib/grafana
54 depends_on:
55 - prometheus
56 networks:
57 - openresty-net
58 restart: unless-stopped
59
60volumes:
61 openresty_logs:
62 prometheus_data:
63 grafana_data:
64
65networks:
66 openresty-net:
67 driver: bridge

.env Template

.env
1# Grafana
2GRAFANA_PASSWORD=secure_grafana_password
3
4# ModSecurity
5PARANOIA_LEVEL=1

Usage Notes

  1. 1OpenResty at http://localhost
  2. 2ModSecurity WAF protection enabled
  3. 3Write custom Lua scripts in /lua folder
  4. 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 file
2cat > docker-compose.yml << 'EOF'
3services:
4 openresty:
5 image: openresty/openresty:alpine
6 ports:
7 - "80:80"
8 - "443:443"
9 volumes:
10 - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro
11 - ./lua:/usr/local/openresty/nginx/lua:ro
12 - ./certs:/etc/nginx/certs:ro
13 - openresty_logs:/usr/local/openresty/nginx/logs
14 networks:
15 - openresty-net
16 restart: unless-stopped
17
18 modsecurity:
19 image: owasp/modsecurity-crs:nginx
20 environment:
21 - PARANOIA=1
22 - ANOMALY_INBOUND=5
23 - ANOMALY_OUTBOUND=4
24 - BACKEND=http://app:8080
25 volumes:
26 - ./modsec-rules:/etc/modsecurity.d/owasp-crs/rules:ro
27 networks:
28 - openresty-net
29 restart: unless-stopped
30
31 app:
32 image: traefik/whoami:latest
33 networks:
34 - openresty-net
35 restart: unless-stopped
36
37 prometheus:
38 image: prom/prometheus:latest
39 ports:
40 - "9090:9090"
41 volumes:
42 - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
43 - prometheus_data:/prometheus
44 networks:
45 - openresty-net
46 restart: unless-stopped
47
48 grafana:
49 image: grafana/grafana:latest
50 ports:
51 - "3000:3000"
52 environment:
53 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
54 volumes:
55 - grafana_data:/var/lib/grafana
56 depends_on:
57 - prometheus
58 networks:
59 - openresty-net
60 restart: unless-stopped
61
62volumes:
63 openresty_logs:
64 prometheus_data:
65 grafana_data:
66
67networks:
68 openresty-net:
69 driver: bridge
70EOF
71
72# 2. Create the .env file
73cat > .env << 'EOF'
74# Grafana
75GRAFANA_PASSWORD=secure_grafana_password
76
77# ModSecurity
78PARANOIA_LEVEL=1
79EOF
80
81# 3. Start the services
82docker compose up -d
83
84# 4. View logs
85docker compose logs -f

One-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 | bash

Troubleshooting

  • 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

Ad Space