```docker-compose.yml version: '3.8' services: nginx: image: owasp/modsecurity:nginx container_name: secure_nginx ports: - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/html:/usr/share/nginx/html:ro - ./nginx/modsecurity/modsecurity.conf:/etc/modsecurity/modsecurity.conf:ro - ./nginx/log:/var/log/nginx restart: always fail2ban: image: crazymax/fail2ban:latest container_name: fail2ban volumes: - ./fail2ban/jail.local:/data/jail.local:ro - ./fail2ban/filter.d:/data/filter.d:ro - ./nginx/log:/var/log/nginx:ro - fail2ban-data:/data restart: always cap_add: - NET_ADMIN - NET_RAW volumes: fail2ban-data: ``` ```conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; modsecurity on; modsecurity_rules_file /etc/modsecurity/modsecurity.conf; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; limit_req_zone $binary_remote_addr zone=limit1:10m rate=5r/s; server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; location / { limit_req zone=limit1 burst=10 nodelay; try_files $uri $uri/ =404; } } } ``` nginx/html/index.html ```