How to Install Apache with ModSecurity on Ubuntu 22.04 LTS

ModSecurity, often referred to as Modsec, is a free, open-source web application firewall (WAF). ModSecurity was created as a module for the Apache HTTP Server. However, since its early days, the WAF has grown and now covers an array of HyperText Transfer Protocol request and response filtering capabilities for various platforms such as Microsoft IIS, Nginx, and Apache.

How the WAF works, the ModSecurity engine is deployed in front of the web application, allowing the engine to scan the incoming and outgoing HTTP connections. ModSecurity is most commonly used in conjunction with the OWASP Core Rule Set (CRS), an open-source set of rules written in ModSecurity’s SecRules language and is highly regarded in the security industry.

OWASP Rule Set with ModSecurity can almost instantly help protect your server against:

  • Bad user agents
  • DDOS
  • Cross website scripting
  • SQL injection
  • Session hijacking
  • Other Threats

During the tutorial, you may notice it is installing the version 2 build, and this is because, unlike Nginx, the beta version of Apache for the Apache/Modsecurity connector has been abandoned and will not work effectively so it is recommended to stay on the original build. Updates are still being carried out, so the version two build is not abandoned.

In the following tutorial, you will learn how to install ModSecurity 3 & OWASP Core Rule Set with Apache on Ubuntu 22.04 LTS Jammy Jellyfish with example configurations.

OWASP has three versions to install; I tested both the 3.3.2 and 4.0.0 RC1, which worked.

Update Ubuntu

First, update your system to ensure all existing packages are up to date.

sudo apt update && sudo apt upgrade -y

Install Latest Apache

First, it is advised to remove any existing installations of Apache and install the latest version, which we will use the Ondrey Surfury PPA.

Remove Existing Apache Installation

Stop the current service if installed with the following command.

sudo systemctl stop apache2

Now remove the existing Apache installation as follows:

sudo apt-get purge apache2 -y && sudo apt autoremove apache2 -y

Add Latest Apache PPA

Now that you have removed your old Apache service, import the PPA.

sudo add-apt-repository ppa:ondrej/apache2 -y

After importing the repository you want, use the following command to update your APT sources list.

sudo apt update

Now that you have installed the PPA and updated the repository list, install Apache with the following command.

sudo apt install apache2 -y

Install/Enable ModSecurity Apache Module

The first step is to install the Apache module included in the default repository of Ubuntu 22.04 with the following command.

sudo apt install libapache2-mod-security2

Once installed, enable the module as follows.

sudo a2enmod security2

Ensure you restart your Apache2 service to reflect the new module and changes.

sudo systemctl restart apache2

Enable ModSecurity Module

Apache ModSecurity’s configurations can be found in /etc/apache2/mods-enabled/security2.conf, which will have a line that contains the following.

IncludeOptional /etc/modsecurity/*.conf


How to Install Apache with ModSecurity on Ubuntu 22.04 LTS

Apache will load all the *.conf files from the /etc/modsecurity/ directory, but you will need to rename the modsecurity.conf-recommended configuration file first.

sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Next, using your favorite text editor in Ubuntu, open the modsecurity.conf file as follows.

sudo nano /etc/modsecurity/modsecurity.conf

By default, ModSecurity configuration has the rule engine specified as (DetectionOnly), which in other words, runs ModSecurity and detects all malicious behavior but does not action blocks or ban and logs all the HTTP transactions that it flags. This should only be used if you have lots of false positives or have increased the security level settings to an extreme level and testing to see if any false positives occur.

In the configuration file, change this behavior to (on), found on line 7.

SecRuleEngine DetectionOnly

Change the line to this to enable ModSecurity:

SecRuleEngine On


How to Install Apache with ModSecurity on Ubuntu 22.04 LTS

Now, you need to locate the following SecAuditLogParts, which is located on line 224.

# Log everything we know about a transaction.
SecAuditLogParts ABDEFHIJZ

This is not correct and needs to be changed. Modify the line to the following:

SecAuditLogParts ABCEFHJKZ

Now save the file using (CTRL+O), then exit (CTRL+X).

Restart your Apache service using the systemctl command to make the changes live.

sudo systemctl restart apache2

Install OWASP Core Rule Set for ModSecurity

ModSecurity on its own does not protect your webserver, and you need to have rules. One of the most famous, respected, and well-known rules is the OWASP CRS rule set. The rules are the most widely used amongst web servers and other WAFs, and most other similar systems base most of their rules on this CRS. Installing this ruleset will automatically give you a great source of protection against most emerging threats on the Internet by detecting malicious actors and blocking them.

Check the OWASP Release tag page to see what is the latest, as the example below may have changed in the future.

First, create the directory that will be the main parent for OWASP.

sudo mkdir /etc/apache2/modsec/

Using the wget command, download the OWASP CRS 3.3.2 archive, which as of this date the latest stable, but do keep in mind four days ago, the pre-release version dropped, so my advice is to check the link a few lines above to see what the releases are looking like for the core ruleset.


For those that want to live on the edge, you can download the nightly build. Only use the nightly if you are prepared to keep re-compiling and checking the CoreRuleSet Github frequently for updates and be more confident at figuring out issues. Technically the nightly can be more secure but potentially can create problems.

For novice users, use the stable version and do not use the below version.


At the time of the creation of the tutorial, the v4.0.0-RC1 pre-release is also available, as mentioned earlier.


Install the Unzip package if you do not have this installed on your server.

sudo apt install unzip -y

Now unzip the archive.

sudo unzip -d /etc/apache2/modsec

Remember, if you have downloaded v4.0 or the nightly, change the commands to reflect this.

OWASP CRS comes with a sample configuration file that you need to rename. It is best to use the CP command and keep a backup for the future in case you need to restart again.

sudo cp /etc/apache2/modsec/coreruleset-3.3.2/crs-setup.conf.example /etc/apache2/modsec/coreruleset-3.3.2/crs-setup.conf

Remember the above command is an example only, be sure to change /coreruleset-3.3.2/ with the exact version of OWASP you decide with.

To enable the rules, open the /etc/etc/apache2/mods-enabled/security2.conf as follows.

sudo nano /etc/apache2/mods-enabled/security2.conf

Once inside the file again, add the following two additional lines:

Include /etc/apache2/modsec/coreruleset-3.3.2/crs-setup.conf
Include /etc/apache2/modsec/coreruleset-3.3.2/rules/*.conf

Remember the above command is an example only, be sure to change /coreruleset-3.3.2/ with the exact version of OWASP you decide with.

Also, blank out the following line or remove it.

IncludeOptional /usr/share/modsecurity-crs/*.load


How to Install Apache with ModSecurity on Ubuntu 22.04 LTS

Save the file (CTRL+O) and exit (CTRL+T).

Restart your Apache service to make the changes live as follows:

sudo systemctl restart apache2

Using and Understanding OWASP Core Rule Set

OWASP CRS has quite a lot of options, the default settings, however, out of the box, will protect most servers immediately without hurting your real visitors and good SEO bots. Below, some areas will be covered to help explain. Further reading would be best to investigate all the options in the configuration files themselves as they have quite a bit of text data to explain what they are.

Open up your CRS-setup.conf file.

sudo nano /etc/apache2/modsec/coreruleset-3.3.2/crs-setup.conf

Note that this is the dev version configuration with additional items compared to version 3.3.

From here, you can modify most of your OWASP CRS settings.


To break it down, ModSecurity has two modes:

Anomaly Scoring Mode

# -- [[ Anomaly Scoring Mode (default) ]] --
# In CRS3, anomaly mode is the default and recommended mode, since it gives the
# most accurate log information and offers the most flexibility in setting your
# blocking policies. It is also called "collaborative detection mode".
# In this mode, each matching rule increases an 'anomaly score'.
# At the conclusion of the inbound rules, and again at the conclusion of the
# outbound rules, the anomaly score is checked, and the blocking evaluation
# rules apply a disruptive action, by default returning an error 403.

Self-Contained Mode

# -- [[ Self-Contained Mode ]] --
# In this mode, rules apply an action instantly. This was the CRS2 default.
# It can lower resource usage, at the cost of less flexibility in blocking policy
# and less informative audit logs (only the first detected threat is logged).
# Rules inherit the disruptive action that you specify (i.e. deny, drop, etc).
# The first rule that matches will execute this action. In most cases this will
# cause evaluation to stop after the first rule has matched, similar to how many
# IDSs function.

Anomaly Scoring is generally, for most users, the best mode to use.

There are four paranoia levels:

  • Paranoia Level 1 – Default level and recommended for most users.
  • Paranoia Level 2 – Advanced users only.
  • Paranoia Level 3 – Expert users only.
  • Paranoia Level 4 – Not recommended at all, except for exceptional circumstances.
# -- [[ Paranoia Level Initialization ]] ---------------------------------------
# The Paranoia Level (PL) setting allows you to choose the desired level
# of rule checks that will add to your anomaly scores.
# With each paranoia level increase, the CRS enables additional rules
# giving you a higher level of security. However, higher paranoia levels
# also increase the possibility of blocking some legitimate traffic due to
# false alarms (also named false positives or FPs). If you use higher
# paranoia levels, it is likely that you will need to add some exclusion
# rules for certain requests and applications receiving complex input.
# - A paranoia level of 1 is default. In this level, most core rules
#   are enabled. PL1 is advised for beginners, installations
#   covering many different sites and applications, and for setups
#   with standard security requirements.
#   At PL1 you should face FPs rarely. If you encounter FPs, please
#   open an issue on the CRS GitHub site and don't forget to attach your
#   complete Audit Log record for the request with the issue.
# - Paranoia level 2 includes many extra rules, for instance enabling
#   many regexp-based SQL and XSS injection protections, and adding
#   extra keywords checked for code injections. PL2 is advised
#   for moderate to experienced users desiring more complete coverage
#   and for installations with elevated security requirements.
#   PL2 comes with some FPs which you need to handle.
# - Paranoia level 3 enables more rules and keyword lists, and tweaks
#   limits on special characters used. PL3 is aimed at users experienced
#   at the handling of FPs and at installations with a high security
#   requirement.
# - Paranoia level 4 further restricts special characters.
#   The highest level is advised for experienced users protecting
#   installations with very high security requirements. Running PL4 will
#   likely produce a very high number of FPs which have to be
#   treated before the site can go productive.
# All rules will log their PL to the audit log;
# example: [tag "paranoia-level/2"]. This allows you to deduct from the
# audit log how the WAF behavior is affected by paranoia level.
# It is important to also look into the variable
# tx.enforce_bodyproc_urlencoded (Enforce Body Processor URLENCODED)
# defined below. Enabling it closes a possible bypass of CRS.

Test OWASP CRS on your Server

To test if OWASP CRS is working on your server, open up your Internet Browser and use the following:

You should receive a 403 forbidden error. If not, then a step has been missed.


How to Install Apache with ModSecurity on Ubuntu 22.04 LTS

The most common problem is missing to change DetectionOnly to On, as covered earlier in the tutorial.

Dealing with False Positives & Custom Rules Exclusion

One of the often never-ending tasks is dealing with false positives, ModSecurity and OWASP CRS do a great job together, but it comes at the cost of your time, but given the protection you get, it is worth it. For starters, never putting the paranoia level up high to start with is the golden rule.

A good rule of thumb is to run the rule set for a few weeks to months with hardly any false positives, then increase, for example, paranoia level 1 to paranoia level 2, so you are not swamped with a ton simultaneously.

Excluding False Positives known Applications

Modsecurity, by default, can whitelist everyday actions that lead to false positives as below:

#SecAction \
# "id:900130,\
#  phase:1,\
#  nolog,\
#  pass,\
#  t:none,\
#  setvar:tx.crs_exclusions_cpanel=1,\
#  setvar:tx.crs_exclusions_dokuwiki=1,\
#  setvar:tx.crs_exclusions_drupal=1,\
#  setvar:tx.crs_exclusions_nextcloud=1,\
#  setvar:tx.crs_exclusions_phpbb=1,\
#  setvar:tx.crs_exclusions_phpmyadmin=1,\
#  setvar:tx.crs_exclusions_wordpress=1,\
#  setvar:tx.crs_exclusions_xenforo=1"

To enable, for example, WordPress, phpBB, and phpMyAdmin as you use all three, uncomment the lines and leave the (1) number intact, change the other services you do not use, for instance, Xenforo to (0) as you do not want to whitelist these rules.

Example below:

SecAction \

You can also modify the syntax, which would be cleaner. For example:

SecAction \

As you can see, removed are the options not needed and added (“) at the end of WordPress for correct syntax.

Excluding Rules Before CRS

To deal with custom exclusions, firstly, you need to change the name from the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS-SAMPLE.conf file with the cp command as follows:

sudo cp /etc/apache2/modsec/coreruleset-3.3.2/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example /etc/apache2/modsec/coreruleset-3.3.2/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

A point to remember when creating exclusion rules, each one must have id:<rule number> and be unique, or else when your test your Apache2 service, you will get an error.

Example “id:1544,phase:1,log,allow,ctl:ruleEngine=off”, the id 1544 cannot be used for a second rule.

For example, some REQUEST_URI’s will raise false positives. The example below is two with Google pagespeed beacon and WMUDEV plugin for WordPress:

SecRule REQUEST_URI "@beginsWith /wp-load.php?wpmudev" "id:1544,phase:1,log,allow,ctl:ruleEngine=off"

SecRule REQUEST_URI "@beginsWith /ngx_pagespeed_beacon" "id:1554,phase:1,log,allow,ctl:ruleEngine=off"

As you can see, any URL that begins with the path will be automatically allowed.

Another option is to whitelist IP addresses; a few ways you can go about this:

SecRule REMOTE_ADDR "^195\.151\.128\.96" "id:1004,phase:1,nolog,allow,ctl:ruleEngine=off"
## or ###
SecRule REMOTE_ADDR "@ipMatch,," "phase:1,id:1313413,allow,ctl:ruleEngine=off"

The @ipMatch can be used more extensively for subnets. If you want to deny a subnet or IP address change, allow to deny. With a bit of know-how, you can also create blacklists and whitelists and configure this with fail2ban. The possibilities can often be endless.

One last example is to disable only rules that trigger false positives, not blanket whitelisting the entire path, as you saw with the first REQUEST_URI example. However, this takes more time and testing.

For instance, if you want to remove rules 941000 and 942999 from your /admin/ area as it keeps triggering false bans and blocks for your team, find in your modsecurity logs file the rule ID and then disable only that ID with RemoveByID as the example below:

SecRule REQUEST_FILENAME "@beginsWith /admin" "id:1004,phase:1,pass,nolog,ctl:ruleRemoveById=941000-942999"

Examples can be found on the ModSecurity GIT wiki page.

WordPress WPRS Rule Set for ModSecurity

Another option for WordPress users is to install and run alongside your OWASP CRS rule set, a well-known project entitled WPRS rule set. As this is optional and isn’t for everyone, the tutorial will not cover it in this section.

However, if you would like to install this for extra protection if you use WordPress on your server, please visit our tutorial on Installing WordPress ModSecurity Rule Set (WPRS).

Create ModSecurity LogRotate file.

ModSecurity logs can overgrow, so you need to set up log rotating as this is not done for you.

First, create and open your ModSecurity rotate file modsec.

sudo nano /etc/logrotate.d/modsec

Add the following code:

        rotate 31

This will keep logs for 31 days. If you prefer to have less, change 31 to 7 days, equally a week’s worth of logs. You should be rotating daily for ModSecurity. If you need to review the log files having a weekly file will be a disaster to sift through, given how large it will be.

Comments and Conclusion

Overall, deploying ModSecurity to your server will provide instant protection. However, patience, time, and dedication to learning will be such a great feature. The last thing you want is to block SEO bots or, more importantly, real users that could be potential customers.


Like to get automatic updates? Follow us on one of our social media accounts!