Skip to main content

NGINX

ModSecurity NGINX Rocky Linux 10: WAF Setup

by ,


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

ModSecurity NGINX Rocky Linux 10 installation provides enterprise-grade Web Application Firewall (WAF) protection for your web applications. ModSecurity inspects HTTP traffic in real-time, blocking SQL injection, cross-site scripting (XSS), and other common web attacks before they reach your application.

This comprehensive guide shows you how to install ModSecurity for NGINX on Rocky Linux 10, AlmaLinux 10, and other Enterprise Linux 10 distributions. You will learn to configure the OWASP Core Rule Set for immediate protection against the most common web vulnerabilities. By the end, you will have ModSecurity NGINX Rocky Linux 10 actively protecting your web applications.

Why Use ModSecurity with NGINX

ModSecurity is the most widely deployed open-source WAF, trusted by organizations worldwide to protect web applications. Here are key benefits of running ModSecurity NGINX Rocky Linux 10:

  • SQL injection protection: Blocks attempts to manipulate database queries through user input
  • Cross-site scripting (XSS) prevention: Stops malicious script injection attacks
  • Remote code execution blocking: Prevents attackers from executing commands on your server
  • Protocol enforcement: Ensures HTTP requests conform to standards
  • Virtual patching: Protect vulnerable applications while waiting for official patches
  • PCI DSS compliance: Helps meet requirement 6.6 for web application firewalls

ModSecurity operates as a transparent proxy, examining every HTTP request and response without modifying your application code. Combined with the OWASP Core Rule Set, it provides comprehensive protection against the OWASP Top 10 vulnerabilities.

Prerequisites

Before installing ModSecurity NGINX Rocky Linux 10 packages, ensure you have:

  • Rocky Linux 10, AlmaLinux 10, RHEL 10, or Oracle Linux 10
  • Root or sudo access to the server
  • NGINX installed (or we will install it in this guide)

The GetPageSpeed repository provides pre-built ModSecurity packages with full SELinux support, eliminating the complex compilation process typically required.

Installation

Step 1: Configure GetPageSpeed Repository

The GetPageSpeed repository provides enterprise-grade NGINX modules including ModSecurity for RHEL-based distributions. Install the repository:

sudo dnf -y install https://extras.getpagespeed.com/release-latest.rpm

This repository contains over 100 NGINX modules, all built and tested for Rocky Linux 10.

Step 2: Install NGINX

If NGINX is not already installed, install it from the GetPageSpeed repository:

sudo dnf -y install nginx
sudo systemctl enable --now nginx

Step 3: Install ModSecurity Module

Install the NGINX ModSecurity module:

sudo dnf -y install nginx-module-security

The installation automatically includes:

  • nginx-module-security: The NGINX connector module
  • libmodsecurity: The ModSecurity engine (libmodsecurity3)
  • nginx-module-security-selinux: SELinux policy for ModSecurity

After installation, you will see instructions for enabling the module:

----------------------------------------------------------------------

The security dynamic module for NGINX has been installed.
To enable this module, add the following to /etc/nginx/nginx.conf
and reload nginx:

    load_module modules/ngx_http_modsecurity_module.so;

----------------------------------------------------------------------

Step 4: Install OWASP Core Rule Set

The OWASP Core Rule Set (CRS) provides a comprehensive set of attack detection rules. Install it with a single command:

sudo dnf -y install nginx-owasp-crs

This package includes:

  • OWASP CRS rules for SQL injection, XSS, and other attacks
  • Pre-configured include file for easy setup
  • Automatic updates via daily cron job

Step 5: Enable ModSecurity

Add the module loading directive at the top of your NGINX configuration:

# /etc/nginx/nginx.conf
load_module modules/ngx_http_modsecurity_module.so;

user nginx;
worker_processes auto;
# ... rest of configuration

Step 6: Configure ModSecurity

Enable ModSecurity in your http or server block and point it to the OWASP CRS configuration:

http {
    # Enable ModSecurity WAF
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec_includes.conf;

    # ... rest of http configuration
}

Test and reload NGINX:

sudo nginx -t && sudo systemctl reload nginx

You should see:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Understanding ModSecurity Configuration

The ModSecurity configuration consists of several components working together.

Main Configuration File

The main configuration file /etc/nginx/modsecurity.conf controls ModSecurity behavior:

# Enable the rule engine
SecRuleEngine On

# Enable request body inspection
SecRequestBodyAccess On

# Maximum request body size (default 13MB)
SecRequestBodyLimit 13107200

# Enable response body inspection
SecResponseBodyAccess On

# Audit logging configuration
SecAuditEngine RelevantOnly
SecAuditLog /var/log/nginx/modsec_audit.log

Key Configuration Directives

SecRuleEngine controls how ModSecurity processes rules:

  • On – Process rules and block malicious requests
  • DetectionOnly – Process rules but only log, never block
  • Off – Disable ModSecurity completely

SecRequestBodyAccess enables inspection of POST data and file uploads. This must be enabled to detect attacks in form submissions.

SecAuditEngine controls audit logging:

  • On – Log all transactions
  • Off – Disable audit logging
  • RelevantOnly – Log only transactions that triggered rules

OWASP CRS Include File

The /etc/nginx/modsec_includes.conf file loads all necessary configurations:

include modsecurity.conf
include owasp-modsecurity-crs/crs-setup.conf
include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
# ... additional rule files
include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
# ... more rules

Verification

After configuring ModSecurity NGINX Rocky Linux 10, verify that the WAF is working correctly.

Check Module Loading

Verify ModSecurity is loaded by checking the error log:

sudo grep ModSecurity /var/log/nginx/error.log

You should see output like:

ModSecurity-nginx v1.0.4 (rules loaded inline/local/remote: 0/710/0)
libmodsecurity3 version 3.0.14

The “710 rules loaded” confirms the OWASP CRS is active.

Test SQL Injection Blocking

Test that ModSecurity blocks SQL injection attempts:

curl -s -o /dev/null -w '%{http_code}\n' 'http://localhost/?id=1%20UNION%20SELECT%20*'

Expected output:

403

A 403 response confirms ModSecurity blocked the attack.

Test XSS Blocking

Test cross-site scripting prevention:

curl -s -o /dev/null -w '%{http_code}\n' 'http://localhost/?q=%3Cscript%3Ealert(1)%3C/script%3E'

Check Audit Logs

View blocked requests in the audit log:

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

The audit log contains detailed information about each blocked request, including the rule that triggered and the request details.

Common Configuration Examples

Per-Location ModSecurity

Enable ModSecurity only for specific locations:

server {
    listen 80;
    server_name example.com;

    # ModSecurity disabled by default
    modsecurity off;

    location /api/ {
        # Enable ModSecurity for API endpoints
        modsecurity on;
        modsecurity_rules_file /etc/nginx/modsec_includes.conf;
        proxy_pass http://backend;
    }

    location /static/ {
        # Static files don't need WAF
        root /var/www/html;
    }
}

Detection-Only Mode

Start with detection-only mode to audit without blocking:

# In /etc/nginx/modsecurity.conf
SecRuleEngine DetectionOnly

Monitor logs in /var/log/nginx/modsec_audit.log to identify false positives before switching to blocking mode.

Custom Rule Exclusions

Disable specific rules that cause false positives:

# In /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

# Disable rule 942100 for specific parameter
SecRuleUpdateTargetById 942100 "!ARGS:custom_field"

# Completely disable a rule
SecRuleRemoveById 920350

Adjusting Paranoia Level

The OWASP CRS paranoia level controls rule strictness. Edit /etc/nginx/owasp-modsecurity-crs/crs-setup.conf:

# Paranoia levels:
# 1 - Default, minimal false positives
# 2 - Moderate, some false positives
# 3 - Strict, more false positives
# 4 - Maximum security, many false positives

SecAction \
    "id:900000,\
    phase:1,\
    nolog,\
    pass,\
    t:none,\
    setvar:tx.paranoia_level=1"

Start with level 1 and increase gradually while monitoring for false positives.

Troubleshooting

ModSecurity Not Blocking Attacks

Symptom: Attacks are not blocked even with ModSecurity enabled

Solutions:

  1. Verify SecRuleEngine On is set (not DetectionOnly)
  2. Check that rules are loaded: look for “rules loaded” in error log
  3. Ensure modsecurity on is in the correct context
  4. Verify the rules file path is correct

High False Positive Rate

Symptom: Legitimate requests being blocked

Solutions:

  1. Start with SecRuleEngine DetectionOnly
  2. Analyze audit logs to identify triggering rules
  3. Add exclusions for specific rules or parameters
  4. Consider lowering paranoia level

Performance Impact

Symptom: Increased latency or CPU usage

Solutions:

  1. Disable response body inspection if not needed:
    nginx
    SecResponseBodyAccess Off
  2. Lower paranoia level
  3. Exclude static file locations from ModSecurity
  4. Use modsecurity off for trusted internal traffic

Module Loading Errors

Symptom: NGINX fails to start with ModSecurity errors

Solutions:

  1. Ensure load_module appears before any other directives
  2. Check file permissions on modsecurity.conf
  3. Verify all included files exist

SELinux Compatibility

The nginx-module-security package from GetPageSpeed includes dedicated SELinux policies. ModSecurity works correctly with SELinux in enforcing mode without any manual configuration.

The package installs:

  • nginx-module-security-selinux: SELinux policy for the NGINX module
  • libmodsecurity-selinux: SELinux policy for the ModSecurity library

These policies allow ModSecurity to:

  • Read configuration files
  • Write to audit log directories
  • Access network sockets for rule updates

Complete Production Configuration

Here is a complete production-ready NGINX configuration with ModSecurity:

# /etc/nginx/nginx.conf
load_module modules/ngx_http_modsecurity_module.so;

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    keepalive_timeout 65;

    # Enable ModSecurity WAF globally
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec_includes.conf;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }

        # Disable WAF for static assets
        location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?)$ {
            modsecurity off;
            root /usr/share/nginx/html;
            expires 30d;
        }
    }
}

Test and apply:

sudo nginx -t && sudo systemctl reload nginx

Monitoring and Maintenance

Log Rotation

ModSecurity audit logs can grow large. The default logrotate configuration handles this automatically. Verify it exists:

cat /etc/logrotate.d/nginx

Rule Updates

The nginx-owasp-crs package includes a daily cron job that checks for rule updates:

cat /etc/cron.daily/modsec

Performance Monitoring

Monitor ModSecurity’s impact on response times:

# Check average request processing time
awk '{sum+=$NF; count++} END {print sum/count}' /var/log/nginx/access.log

For more NGINX security and performance guides:

Conclusion

ModSecurity NGINX Rocky Linux 10 setup provides robust protection against web application attacks. With the GetPageSpeed repository, installation requires just two packages: nginx-module-security and nginx-owasp-crs. The pre-built packages include full SELinux support, eliminating the complex compilation typically required.

Start with detection-only mode to identify potential false positives, then switch to blocking mode once you have tuned the rules for your application. The OWASP Core Rule Set provides comprehensive protection against SQL injection, XSS, and other common vulnerabilities out of the box.

For any production NGINX deployment handling sensitive data or user input, ModSecurity provides an essential layer of defense. The investment in proper WAF configuration pays dividends in reduced security incidents and improved compliance posture.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.