WAFPlanet

How to Install and Configure ModSecurity with NGINX

Complete guide to deploying ModSecurity 3.x with NGINX for free, open-source WAF protection using the OWASP Core Rule Set.

45-60 minutes intermediate 10 steps
Last updated: Dec 29, 2025

ModSecurity is the industry-standard open-source WAF, protecting millions of websites worldwide. Combined with NGINX, it provides powerful, customizable protection against OWASP Top 10 vulnerabilities, SQL injection, cross-site scripting, and countless other web attacks—all at zero licensing cost.

This guide walks you through installing ModSecurity 3.x (libmodsecurity) with the NGINX connector, configuring the OWASP Core Rule Set, and tuning the setup for production use. By the end, you'll have enterprise-grade WAF protection running on your NGINX server.

Prerequisites

  • NGINX installed and running (open source or Plus)
  • Root or sudo access to your server
  • Ubuntu 20.04+, Debian 11+, or RHEL/CentOS 8+ (other distros may vary)
  • Basic familiarity with NGINX configuration
  • Git installed for cloning repositories

Step-by-Step Guide

1

Install ModSecurity 3.x Dependencies

ModSecurity 3.x (libmodsecurity) requires several dependencies. Install them based on your distribution:

Ubuntu/Debian:

sudo apt update
sudo apt install -y apt-utils autoconf automake build-essential \
  git libcurl4-openssl-dev libgeoip-dev liblmdb-dev libpcre2-dev \
  libtool libxml2-dev libyajl-dev pkgconf wget zlib1g-dev

RHEL/CentOS/Rocky:

sudo dnf install -y gcc-c++ flex bison yajl curl-devel zlib-devel \
  pcre2-devel autoconf automake git curl make libxml2-devel \
  pkgconfig libtool httpd-devel lmdb-devel GeoIP-devel
Tip: These dependencies are required to compile ModSecurity from source. Package managers don't always have the latest version.
2

Clone and Build ModSecurity 3.x

Clone the ModSecurity repository and build the library:

cd /opt
sudo git clone --depth 1 -b v3/master --single-branch https://github.com/owasp-modsecurity/ModSecurity
cd ModSecurity

# Initialize and update submodules
sudo git submodule init
sudo git submodule update

# Build and install
sudo ./build.sh
sudo ./configure
sudo make
sudo make install
Tip: Using --depth 1 reduces download size significantly by only fetching the latest commit.
Warning: The build process takes 10-15 minutes depending on your server's resources. Don't interrupt it.
3

Clone and Build the NGINX Connector

The NGINX ModSecurity connector integrates libmodsecurity with NGINX as a dynamic module:

# Clone the connector
cd /opt
sudo git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git

# Get your NGINX version
nginx -v

# Download matching NGINX source (replace version as needed)
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# Build the dynamic module
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules

# Copy module to NGINX modules directory
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
Warning: The NGINX source version MUST match your installed NGINX version exactly. Check with 'nginx -v'.
4

Enable the ModSecurity Module in NGINX

Load the ModSecurity module in your NGINX configuration:

Add this line at the very top of /etc/nginx/nginx.conf (before the events block):

load_module modules/ngx_http_modsecurity_module.so;

Test the configuration:

sudo nginx -t

You should see: syntax is ok and test is successful.

Tip: If you get module load errors, verify the .so file exists and has correct permissions (644).
5

Create ModSecurity Configuration

Set up the ModSecurity configuration directory and base configuration:

# Create directory structure
sudo mkdir -p /etc/nginx/modsec

# Copy the recommended configuration
sudo cp /opt/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf

# Copy the Unicode mapping file
sudo cp /opt/ModSecurity/unicode.mapping /etc/nginx/modsec/

Edit /etc/nginx/modsec/modsecurity.conf and change the engine from detection to blocking:

# Change this line:
SecRuleEngine DetectionOnly

# To (when ready for production):
SecRuleEngine On
Warning: Keep SecRuleEngine DetectionOnly initially to test without blocking legitimate traffic. Switch to On after tuning.
6

Install OWASP Core Rule Set (CRS)

The OWASP Core Rule Set provides comprehensive protection against common attacks:

cd /etc/nginx/modsec
sudo git clone https://github.com/coreruleset/coreruleset.git
cd coreruleset

# Create configuration from example
sudo cp crs-setup.conf.example crs-setup.conf

Create a main rules file at /etc/nginx/modsec/main.conf:

Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf
Tip: The CRS is actively maintained and updated regularly. Consider setting up periodic updates via cron or your deployment pipeline.
7

Enable ModSecurity in NGINX Server Blocks

Enable ModSecurity for your sites by adding directives to your server blocks:

server {
    listen 80;
    server_name example.com;

    # Enable ModSecurity
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec/main.conf;

    location / {
        proxy_pass http://backend;
        # ... other directives
    }
}

Reload NGINX to apply changes:

sudo nginx -t && sudo systemctl reload nginx
Tip: You can enable ModSecurity globally in the http block or selectively per server/location block.
8

Test the WAF

Verify ModSecurity is working by sending a test attack:

# This should be blocked (SQL injection attempt)
curl -I 'http://your-server.com/?id=1%20OR%201=1'

# This should be blocked (XSS attempt)
curl -I 'http://your-server.com/?q=<script>alert(1)</script>'

Check the ModSecurity audit log:

sudo tail -f /var/log/modsec_audit.log

You should see entries showing the blocked requests with rule IDs and attack details.

Warning: If requests aren't being blocked, verify SecRuleEngine is set to On and NGINX was reloaded.
9

Configure Logging

Configure ModSecurity logging in /etc/nginx/modsec/modsecurity.conf:

# Audit log settings
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsec_audit.log

# Debug log (disable in production)
SecDebugLog /var/log/modsec_debug.log
SecDebugLogLevel 0

Create the log files with correct permissions:

sudo touch /var/log/modsec_audit.log
sudo chown www-data:www-data /var/log/modsec_audit.log
Tip: Set SecDebugLogLevel to 3-9 temporarily when troubleshooting rule issues, but keep it at 0 in production.
10

Tune for False Positives

After running in DetectionOnly mode, review logs for false positives. Common tuning approaches:

Exclude specific rules:

# In /etc/nginx/modsec/crs-setup.conf or a custom file:
SecRuleRemoveById 942100  # Disable specific rule
SecRuleRemoveByTag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"  # Disable by tag

Exclude rules for specific URLs:

SecRule REQUEST_URI "@beginsWith /api/upload" \
  "id:1000,phase:1,pass,nolog,\
   ctl:ruleRemoveById=200002"

Adjust paranoia level:

In crs-setup.conf, set the paranoia level (1=low false positives, 4=maximum security):

SecAction "id:900000,phase:1,pass,t:none,\
  setvar:tx.blocking_paranoia_level=1"
Tip: Start with paranoia level 1 and increase gradually as you tune out false positives for your application.

Conclusion & Next Steps

Your NGINX server is now protected by ModSecurity with the OWASP Core Rule Set. You have enterprise-grade WAF protection at zero licensing cost.

Next steps:

  • Monitor /var/log/modsec_audit.log regularly for blocked attacks and false positives
  • After 1-2 weeks of DetectionOnly mode, switch SecRuleEngine to On
  • Set up log rotation for the audit log
  • Consider integrating logs with your SIEM (ELK, Splunk, etc.)
  • Schedule regular CRS updates (monthly recommended)
  • Document any custom rule exclusions for your team

Troubleshooting

Module fails to load: undefined symbol

This means the NGINX connector was compiled against a different NGINX version. Recompile the module using the exact NGINX source version matching your installed NGINX (check with nginx -v).

Legitimate requests being blocked

Check /var/log/modsec_audit.log for the rule ID causing the block. Either create an exclusion rule or adjust the paranoia level. Common culprits: file uploads, rich text editors, JSON APIs.

No logs appearing in audit log

Verify the log file exists and has write permissions for the NGINX user (www-data or nginx). Check that SecAuditEngine is not set to Off.

Performance degradation

ModSecurity adds some latency (typically 1-5ms). If you see significant slowdown: reduce the number of active rules, lower the request body limit (SecRequestBodyLimit), or consider caching more aggressively in NGINX.

make fails during ModSecurity build

Usually a missing dependency. Review error messages carefully. On Ubuntu, ensure you have the -dev versions of packages (e.g., libcurl4-openssl-dev, not just libcurl4).

Frequently Asked Questions

Should I use ModSecurity 2.x or 3.x with NGINX?

Use ModSecurity 3.x (libmodsecurity). Version 2.x was designed for Apache and only works with NGINX through cumbersome workarounds. Version 3.x was rebuilt as a standalone library with a native NGINX connector, offering better performance and compatibility.

How does ModSecurity impact NGINX performance?

ModSecurity typically adds 1-5ms latency per request, depending on rule complexity and request size. For most applications, this is negligible. High-traffic sites should benchmark and consider adjusting SecRequestBodyLimit and paranoia levels to optimize performance.

Can I use ModSecurity with NGINX Plus?

Yes, the same ModSecurity connector works with NGINX Plus. However, NGINX Plus users might also consider NGINX App Protect, F5's commercial WAF that's specifically optimized for NGINX Plus with additional features and support.

How do I update the OWASP Core Rule Set?

Navigate to the coreruleset directory and pull the latest changes: cd /etc/nginx/modsec/coreruleset && sudo git pull. Then reload NGINX. Consider testing updates in a staging environment first, as new rules may cause unexpected blocks.

What's the difference between DetectionOnly and On?

DetectionOnly logs potential attacks but doesn't block them—requests still reach your application. On mode actively blocks malicious requests. Always start with DetectionOnly to identify false positives before switching to On in production.

Can I use ModSecurity to protect multiple sites on one NGINX server?

Yes. You can enable ModSecurity globally in the http block for all sites, or selectively per server block. You can also use different rule configurations per site by specifying different modsecurity_rules_file paths in each server block.

Related Guides