Skip to main content
Back to blog
April 28, 2026|9 min read|Antoine Duno

Apache Security Hardening: The Complete Configuration Guide

Apache security hardening turns a default, information-leaking server into a production-grade, defense-in-depth installation. This guide covers every critical directive — from hiding server tokens to enforcing modern TLS — with copy-paste config snippets.

ZeriFlow Team

1,160 words

Apache Security Hardening: The Complete Configuration Guide

Apache security is not automatic. A default Apache installation broadcasts its version and module list to every visitor, accepts outdated TLS protocols, and provides no security headers whatsoever. This guide fixes every one of those issues with practical configuration snippets you can apply immediately.

Start by running a free ZeriFlow scan on your domain to establish a baseline security score. Then work through each section below and scan again at the end to confirm your improvements.


Hiding Server Information: ServerTokens and ServerSignature

By default, Apache includes its full version number and loaded modules in HTTP response headers and error pages. This is reconnaissance gold for attackers — they know exactly which version-specific vulnerabilities to attempt.

Add these directives to your main Apache configuration (usually /etc/apache2/apache2.conf or /etc/httpd/conf/httpd.conf):

apache
ServerTokens Prod
ServerSignature Off
  • ServerTokens Prod: Reduces the Server header to Apache only, removing the version number and OS information.
  • ServerSignature Off: Removes the server information footer from error pages and directory listings.

Disable directory listings:

apache
Options -Indexes

This prevents Apache from generating a file browser when no index file exists in a directory — a common source of accidental information disclosure.

Disable unused modules: Apache ships with many modules enabled by default that you may not need. Run apache2ctl -M to list active modules and disable anything unused with a2dismod:

bash
a2dismod status  # Removes /server-status endpoint
a2dismod info    # Removes /server-info endpoint
a2dismod autoindex  # Disables directory listing (alternative to -Indexes)

SSL/TLS Configuration: Enforcing Modern Protocols

Apache's default SSL configuration accepts protocols and ciphers that have known vulnerabilities. Here is a production-ready SSL configuration using mod_ssl:

apache
<VirtualHost *:443>
    ServerName yourdomain.com
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/yourdomain.crt
    SSLCertificateKeyFile /etc/ssl/private/yourdomain.key
    SSLCertificateChainFile /etc/ssl/certs/chain.crt

    # Only TLS 1.2 and 1.3
    SSLProtocol -all +TLSv1.2 +TLSv1.3

    # Modern cipher suite (Mozilla Intermediate)
    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:DHE-RSA-AES128-GCM-SHA256
    SSLHonorCipherOrder off

    # OCSP Stapling
    SSLUseStapling on
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors off
</VirtualHost>

# Required for OCSP Stapling (outside VirtualHost)
SSLStaplingCache 'shmcb:/var/run/apache2/stapling_cache(128000)'

HTTP to HTTPS redirect:

apache
<VirtualHost *:80>
    ServerName yourdomain.com
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

Security Headers via mod_headers

Apache's mod_headers module lets you add security headers to every response. Ensure the module is enabled first:

bash
a2enmod headers
systemctl restart apache2

Then add these to your VirtualHost or to a global conf file:

apache
<IfModule mod_headers.c>
    Header always set X-Frame-Options 'DENY'
    Header always set X-Content-Type-Options 'nosniff'
    Header always set X-XSS-Protection '1; mode=block'
    Header always set Referrer-Policy 'strict-origin-when-cross-origin'
    Header always set Permissions-Policy 'geolocation=(), microphone=(), camera=()'
    Header always set Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload'
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https:; frame-ancestors 'none';"

    # Remove potentially leaky headers
    Header unset X-Powered-By
    Header unset X-AspNet-Version
    Header unset X-AspNetMvc-Version
</IfModule>

The always keyword ensures headers are sent on all response codes, including 3xx, 4xx, and 5xx — not just 200 OK responses.


.htaccess Security Configuration

For shared hosting or situations where you cannot modify the main Apache configuration, .htaccess files provide a powerful alternative. Place this in your site's root directory:

apache
# Disable directory browsing
Options -Indexes -Includes

# Enable rewrite engine
RewriteEngine On

# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# Block access to sensitive files
<FilesMatch '(\.(bak|conf|dist|fla|inc|ini|log|psd|sh|sql|swp|yaml|yml)|~)$'>
    Require all denied
</FilesMatch>

# Block access to .git directory
RedirectMatch 404 /\.git

# Security headers (requires mod_headers)
<IfModule mod_headers.c>
    Header always set X-Frame-Options 'SAMEORIGIN'
    Header always set X-Content-Type-Options 'nosniff'
    Header always set Strict-Transport-Security 'max-age=31536000'
</IfModule>

# Limit request size to prevent DoS
LimitRequestBody 10485760

# Disable HTTP TRACE method
TraceEnable off

Note: .htaccess is processed on every request, adding slight overhead. For performance-critical applications, apply these settings in httpd.conf or a VirtualHost block with AllowOverride None and move all rules to the main configuration.


Rate Limiting With mod_ratelimit and mod_evasive

Apache does not have built-in rate limiting as flexible as Nginx, but mod_evasive provides basic DDoS and brute-force protection:

bash
apt-get install libapache2-mod-evasive
a2enmod evasive

Configuration in /etc/apache2/mods-available/evasive.conf:

apache
<IfModule mod_evasive20.c>
    DOSHashTableSize    2048
    DOSPageCount        5
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   600
    DOSLogDir           /var/log/apache2/evasive
    DOSEmailNotify      your-email@domain.com
</IfModule>

This blocks any IP that requests the same page more than 5 times per second or makes more than 50 requests to the site per second, for 600 seconds.


Verify Everything With ZeriFlow

After completing these changes, run apachectl -t to verify there are no syntax errors, then restart Apache with systemctl restart apache2.

Run a ZeriFlow security scan on your domain to verify: - Security headers are present and correctly formatted - TLS protocol version and cipher strength - Server information disclosure has been eliminated - HTTPS redirect is working - HSTS header configuration


FAQ

### Q: Should I use .htaccess or VirtualHost for security headers? A: VirtualHost (or the main httpd.conf) is always preferred for performance. .htaccess is parsed on every request, while VirtualHost directives are loaded once at startup. Use .htaccess only when you do not have access to the main configuration files.

### Q: How do I check which Apache modules are currently loaded? A: Run apache2ctl -M (Ubuntu/Debian) or httpd -M (RHEL/CentOS). This lists all static and shared modules. Disable any module you do not actively use with a2dismod <module_name>.

### Q: Does ServerTokens Prod completely hide that I am running Apache? A: It hides the version, but the Server: Apache header still reveals the server software. Completely hiding this requires the mod_security module with a custom SecServerSignature directive, or a reverse proxy (like Cloudflare) in front of your server.

### Q: Can I use Let's Encrypt certificates with this Apache SSL configuration? A: Yes. Certbot automatically generates a compatible Apache SSL configuration when you run certbot --apache. Review the generated configuration against the snippet above to ensure strong protocols and ciphers are enforced — Certbot's defaults are good but occasionally conservative on older systems.


Conclusion

Apache security hardening is a systematic process. Start with information disclosure (ServerTokens, ServerSignature), move to TLS hardening, add security headers, and finish with rate limiting and access controls. Each layer adds protection that the previous layers cannot provide alone.

The configurations in this guide follow the Mozilla SSL Configuration guidelines and OWASP security header recommendations — the same standards used by major enterprises worldwide.

Scan your Apache server with ZeriFlow after applying these settings. The free scan runs 80+ security checks and gives you an objective score with specific, actionable findings for any remaining issues.

Ready to check your site?

Run a free security scan in 30 seconds.

Related articles

Keep reading