Updated: 29 September 2026 · Applies to: ModSecurity 2.9 with the OWASP Core Rule Set 3.3 on Apache 2.4: AlmaLinux and Rocky Linux 9, RHEL 9, Ubuntu 24.04 and 26.04, Debian 13
ModSecurity is a web application firewall (WAF) module for Apache. Together with the OWASP Core Rule Set (CRS), it blocks common attacks such as SQL injection and cross-site scripting before they reach your application. We tested the setup below on AlmaLinux 9 (ModSecurity 2.9.6, CRS 3.3.5) and Debian 13 (ModSecurity 2.9.11, CRS 3.3.7): normal requests passed, and test attacks were blocked with "403 Forbidden".
AlmaLinux, Rocky Linux and RHEL 9
dnf install mod_security mod_security_crs systemctl restart httpd
The module is configured in /etc/httpd/conf.d/mod_security.conf with SecRuleEngine On, so it blocks right away. The rules are in /etc/httpd/modsecurity.d/, and your own rules or exceptions go into /etc/httpd/modsecurity.d/local_rules/. On version 10, mod_security comes from EPEL and the CRS is not packaged; download it from the OWASP CRS project.
Ubuntu and Debian
apt install libapache2-mod-security2 modsecurity-crs cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
The recommended file starts in detection mode (SecRuleEngine DetectionOnly), which only logs. Watch the log for a while (see below), then switch to blocking by changing that line in /etc/modsecurity/modsecurity.conf to:
SecRuleEngine On
apache2ctl configtest && systemctl restart apache2
The package loads the CRS automatically from /usr/share/modsecurity-crs/.
Test it
curl -s -o /dev/null -w "%{http_code}\n" "http://localhost/"
curl -s -o /dev/null -w "%{http_code}\n" "http://localhost/?q=<script>alert(1)</script>"
The first request should return 200, the second 403. Check that the module is loaded with apachectl -M | grep security2.
Logs and false positives
- Blocked requests are logged in the Apache error log with the rule ID, and in detail in
/var/log/httpd/modsec_audit.logor/var/log/apache2/modsec_audit.log. - If a legitimate request is blocked, note the rule
idfrom the log and exclude only that rule, and only where needed, for example for one URL:SecRule REQUEST_URI "@beginsWith /wp-admin/" "id:1000001,phase:1,pass,nolog,ctl:ruleRemoveById=941100"
Put such exceptions in the local rules folder (AlmaLinux, Rocky Linux) or a new file in/etc/modsecurity/(Ubuntu, Debian), and use your own IDs above 1000000. - Start with the default paranoia level. Higher levels catch more but block more legitimate traffic.
On cPanel servers
Do not install these packages on a cPanel server. Use WHM instead: Security Center > ModSecurity Configuration for the engine, and ModSecurity Vendors for the OWASP rule set.
Official documentation: OWASP CRS documentation and ModSecurity 2.x reference manual.