Type something to search...
How to secure an Apache web server?

How to secure an Apache web server?

To secure an Apache web server, keep Apache updated, hide its version and OS details, disable modules you don't use, serve everything over HTTPS with TLS 1.2 and 1.3 only, add security headers, deny access to the filesystem by default and only allow your web root, turn off directory listing, restrict .htaccess overrides, block hidden and sensitive files, limit request sizes and timeouts, and consider a web application firewall such as ModSecurity. Always run apachectl configtest before reloading.

Apache HTTP Server has powered websites for decades and remains widely used, especially on shared hosting and with applications like WordPress. Its flexibility is a strength, but it also means there are many settings to get right. This guide walks through a practical hardening checklist for Apache 2.4 on Ubuntu and Debian, with notes for RHEL-based systems, and includes ready-to-use configuration examples.

Before You Start

  • Back up your configuration:
sudo cp -a /etc/apache2 /etc/apache2.backup-$(date +%F)

On RHEL, Rocky Linux, and AlmaLinux, the configuration lives in /etc/httpd/ and the service is called httpd.

  • Test before reloading:
sudo apachectl configtest
sudo systemctl reload apache2
  • Know the layout: On Ubuntu and Debian, global settings are in /etc/apache2/apache2.conf, extra config snippets in /etc/apache2/conf-available/, and sites in /etc/apache2/sites-available/. Enable them with a2enconf, a2ensite, and a2enmod.

Step 1: Keep Apache Updated

Apache receives regular security releases. Install updates from your distribution and enable automatic security updates. Check your version:

apache2 -v

On RHEL-based systems, use httpd -v.

Step 2: Hide Version and OS Information

By default, Apache can reveal its exact version and operating system in the Server header and on error pages. On Ubuntu and Debian, edit /etc/apache2/conf-available/security.conf:

ServerTokens Prod
ServerSignature Off
TraceEnable Off
  • ServerTokens Prod reduces the header to Server: Apache.
  • ServerSignature Off removes version info from error pages.
  • TraceEnable Off disables the HTTP TRACE method, which isn't needed and has been abused in the past.

Make sure the config is enabled:

sudo a2enconf security
sudo apachectl configtest && sudo systemctl reload apache2

On RHEL-based systems, add these lines to a file like /etc/httpd/conf.d/security.conf.

Step 3: Disable Unused Modules

Every loaded module adds code that could contain vulnerabilities. List what's enabled:

apache2ctl -M

Common modules you may not need:

  • status (server-status page), unless you've restricted it
  • autoindex (directory listings)
  • userdir (per-user web folders)
  • cgi or cgid, if you don't run CGI scripts
  • dav and dav_fs, unless you use WebDAV
  • info (server-info page)

Disable them on Ubuntu and Debian:

sudo a2dismod autoindex status userdir
sudo apachectl configtest && sudo systemctl reload apache2

Some modules are dependencies for others, so read any warnings a2dismod prints. On RHEL-based systems, comment out the relevant LoadModule lines in /etc/httpd/conf.modules.d/.

If you keep mod_status, make sure it's only accessible locally:

<Location "/server-status">
    SetHandler server-status
    Require local
</Location>

Step 4: Use a Modern MPM With PHP-FPM

The older mpm_prefork with mod_php runs PHP inside Apache processes. The recommended setup today is mpm_event with PHP-FPM, which separates PHP from Apache and lets you run each site's PHP as its own user:

sudo apt install php8.3-fpm
sudo a2dismod php8.3 mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl restart apache2

Replace 8.3 with your PHP version. Running PHP separately means a compromised PHP script doesn't automatically have the same access as the web server.

Step 5: Enforce Modern TLS

Enable SSL and get free certificates with Certbot:

sudo a2enmod ssl headers
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com

Then set a strong global TLS policy, for example in /etc/apache2/conf-available/tls-hardening.conf. These settings follow Mozilla's "intermediate" recommendations:

SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
SSLSessionTickets off
SSLCompression off

Enable it:

sudo a2enconf tls-hardening
sudo apachectl configtest && sudo systemctl reload apache2

SSLCipherSuite here applies to TLS 1.2. TLS 1.3 uses secure ciphers by default.

Redirect HTTP to HTTPS

In your port 80 virtual host:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    Redirect permanent / https://example.com/
</VirtualHost>

Certbot can add this for you, but a simple Redirect is clearer than rewrite rules.

Step 6: Add Security Headers

With mod_headers enabled, add headers globally or in each HTTPS virtual host:

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>
  • Only use includeSubDomains in HSTS if all subdomains support HTTPS.
  • A Content Security Policy provides the strongest protection against cross-site scripting but must be tailored to your site. Start with Content-Security-Policy-Report-Only and adjust.
  • Use Header always set so headers are also sent on error responses.

Step 7: Deny Filesystem Access by Default

Apache 2.4 uses Require directives for access control. The secure pattern is to deny everything at the root of the filesystem, then allow only your web directories. Debian and Ubuntu's apache2.conf already includes this, but confirm it's there:

<Directory />
    Options None
    AllowOverride None
    Require all denied
</Directory>

<Directory /var/www/>
    Options -Indexes +FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

Avoid the old Apache 2.2 syntax (Order allow,deny and Deny from all). It only works through the compatibility module mod_access_compat and mixing the two styles can produce confusing results.

Step 8: Disable Directory Listing

Options -Indexes in the block above stops Apache from listing a folder's contents when there's no index file. Check that no virtual host re-enables it:

sudo grep -rn "Indexes" /etc/apache2/

Look for Options Indexes or +Indexes. Disabling mod_autoindex (Step 3) also prevents listings entirely.

Step 9: Restrict .htaccess Overrides

.htaccess files are convenient, but they let any directory change server behaviour, and they slow Apache down because it checks for them on every request. If you control the server, put rules in the virtual host config and set:

AllowOverride None

Some applications, including WordPress, rely on .htaccess for permalinks. In that case, allow only what's needed for that site's directory:

<Directory /var/www/example.com/public>
    AllowOverride FileInfo
    Require all granted
</Directory>

FileInfo allows rewrite rules without allowing overrides for things like authentication or options. Some plugins write other directives to .htaccess, so test your application after changing this.

Step 10: Block Hidden and Sensitive Files

Prevent access to files like .git, .env, .htpasswd, and backups:

# Block hidden files and folders, except .well-known for certificate validation.
<LocationMatch "/\.(?!well-known)">
    Require all denied
</LocationMatch>

# Block backup, config, and log files.
<FilesMatch "\.(bak|conf|dist|ini|log|old|orig|save|sql|swp|tmp)$">
    Require all denied
</FilesMatch>

Debian's default configuration already denies .ht* files, but the rules above cover a wider range.

Step 11: Block PHP in Upload Folders

For applications that accept uploads, prevent PHP from running in upload directories. For WordPress:

<Directory /var/www/example.com/public/wp-content/uploads>
    <FilesMatch "\.(php|phtml|php[0-9]|phar)$">
        Require all denied
    </FilesMatch>
</Directory>

If you can't edit the virtual host, the inner FilesMatch block also works in an .htaccess file inside the uploads folder, as long as overrides allow it.

Step 12: Limit Request Size and Timeouts

Protect against slow and oversized requests. In your global config:

Timeout 60
KeepAliveTimeout 5
LimitRequestBody 16777216
LimitRequestFields 100
LimitRequestFieldSize 8190

LimitRequestBody is in bytes (the example is 16 MB). Set it to match the largest upload your application needs. Recent Apache versions set a default limit of 1 GB.

Enable mod_reqtimeout (usually on by default) to drop connections that send headers or bodies too slowly, which helps against slow-request attacks:

<IfModule reqtimeout_module>
    RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>

Step 13: Protect Admin Areas

Restrict sensitive paths by IP:

<Location "/admin">
    Require ip 203.0.113.10
</Location>

Or add Basic Authentication as an extra layer:

sudo htpasswd -c /etc/apache2/.htpasswd adminuser
<Location "/admin">
    AuthType Basic
    AuthName "Restricted"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Location>

Keep password files outside the web root, as shown.

Step 14: Add a Web Application Firewall

ModSecurity is an open-source WAF that works with Apache. Paired with the OWASP Core Rule Set, it blocks many common attacks like SQL injection and cross-site scripting.

On Ubuntu and Debian:

sudo apt install libapache2-mod-security2 modsecurity-crs
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

The recommended config starts in detection-only mode. Watch the audit log for false positives first, then switch to blocking by editing /etc/modsecurity/modsecurity.conf:

SecRuleEngine On

Reload Apache afterward. Expect to tune some rules for applications like WordPress, which can trigger false positives in the admin area.

Step 15: Run With Minimal Privileges and Correct Permissions

Apache's worker processes run as www-data on Ubuntu and Debian (apache on RHEL). Web files should be owned by a deploy user, not the web server user, and only directories that need to be writable should be:

sudo chown -R deploy:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;

Give writable access only to folders like uploads or cache. With PHP-FPM, you can run each site's PHP pool as its own user for even better isolation.

Step 16: Log, Monitor, and Test

  • Keep access and error logs enabled and rotated.
  • Pair logs with Fail2Ban to block IPs that probe for vulnerabilities.
  • Check headers and version hiding from outside:
curl -sI https://example.com
  • Use SSL Labs' server test and Mozilla Observatory to check TLS and headers.

FAQ: Securing Apache

Yes. Apache 2.4 is actively maintained and receives regular security updates. Like any server software, it needs to be kept updated and configured carefully.

Set ServerTokens Prod and ServerSignature Off in your Apache configuration, then reload Apache. The Server header will show only Apache, without version or OS details.

Use Require directives, such as Require all denied and Require ip. The Order, Allow, and Deny directives are from Apache 2.2 and only work through a compatibility module.

If you control the server, putting rules in the virtual host and setting AllowOverride None is more secure and faster. If your application relies on .htaccess, allow only the override types it needs, such as FileInfo.

ModSecurity is an open-source web application firewall module for Apache. Combined with the OWASP Core Rule Set, it inspects requests and blocks common attacks like SQL injection and cross-site scripting.

PHP-FPM with mpm_event is generally preferred. It separates PHP from Apache, lets each site run under its own user, and performs better under load.


Conclusion

Hardening Apache is about reducing what it exposes and tightening what's left. Hide version details, disable unused modules, enforce TLS 1.2 and 1.3, add security headers, deny filesystem access by default, turn off directory listings, and limit .htaccess overrides. Block hidden files and PHP in upload folders, and set sensible limits on request sizes and timeouts.

For extra protection, run PHP through PHP-FPM, restrict admin areas, and add ModSecurity with the OWASP Core Rule Set. Test every change with apachectl configtest, verify the results from outside, and keep Apache updated. With those habits, Apache remains a solid and secure choice for hosting your websites.

Tags :
Share :

Related Posts

What are the best WordPress security plugins?

What are the best WordPress security plugins?

The best WordPress security plugins for most sites are Wordfence, Sucuri Security, Solid Security, MalCare, All-In-One Security (AIOS), Patchstack, a

Dive Deeper
What are the most common website security threats?

What are the most common website security threats?

The most common website security threats are vulnerable or outdated software, weak and stolen passwords, malware infections, injection attacks like S

Dive Deeper
How does GDPR affect website security?

How does GDPR affect website security?

GDPR affects website security by turning it from a good habit into a legal obligation. If your website collects personal data from people in the EU (

Dive Deeper