The httpd.conf File Is Your First Line of Defence
The Apache httpd.conf file controls how your web server behaves under every request it receives. It determines which protocols are accepted, what information is revealed about your server, how requests are processed, and what resources are available to visitors. Getting this configuration right means reducing your attack surface significantly. Getting it wrong means leaving doors open that an attacker will find during automated reconnaissance.
For anyone running a web server, the settings in this file matter more than most people realise. Apache has been a stable part of the web infrastructure for decades, and while newer options exist, it remains one of the most widely deployed web servers in production environments. This means attackers have detailed knowledge of its default behaviour, which makes proper configuration even more important.
This guide walks through the practical settings that make a measurable difference to Apache security. The focus is on Debian and Ubuntu systems, though the concepts apply to any Apache installation. Before making changes, back up your current configuration so you can restore it if something goes wrong.
Back Up Before Making Any Changes
Configuration changes that break Apache are recoverable if you have a known-good copy to restore from. Take a moment to back up the main config file and any security-related includes before you start.
cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.backup
cp /etc/apache2/conf-available/security.conf /etc/apache2/conf-available/security.conf.backup
On Debian and Ubuntu systems, the main Apache configuration is typically at /etc/apache2/apache2.conf with additional configs in /etc/apache2/conf-available/. On RHEL and CentOS, the main config is usually /etc/httpd/conf/httpd.conf with extras in /etc/httpd/conf.d/. Know which system you are working with before making changes, as file paths differ between distributions.
For broader server security context, the steps in this guide work well alongside a Ubuntu server hardening checklist that covers the wider server environment beyond just the web server.
Remove Server Information Leakage
By default, Apache sends detailed information about itself in every HTTP response. This includes the version number, loaded modules, and operating system details. Attackers use this information to identify known vulnerabilities in your specific version before attempting an exploit.
Two directives control what information Apache reveals. Setting them correctly removes useful reconnaissance data from every response.
ServerTokens Prod
ServerSignature Off
ServerTokens Prod tells Apache to respond with Server: Apache only, without version numbers or module information. ServerSignature Off removes the version number from server-generated error pages. Both settings belong in the global configuration or the security configuration include file.
Restrict SSL Protocols and Ciphers
If your Apache server handles HTTPS traffic, the SSL configuration is the most critical hardening step. Many default Apache installations still allow SSLv3 and early TLS versions that are vulnerable to known attacks. These legacy protocols should be disabled on any publicly accessible server.
Restrict to TLS 1.2 and TLS 1.3 only, and configure a strong cipher suite that supports forward secrecy.
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
SSLCompression off
The SSLProtocol line disables every protocol version before TLS 1.2. If you need to support legacy clients that cannot use TLS 1.2, weigh that requirement carefully against the security risk. For most business applications, TLS 1.2 is the minimum acceptable standard.
SSLHonorCipherOrder on forces the server's cipher preference rather than the client's, which matters because server-side cipher lists should be ordered by strength. SSLCompression off disables compression to prevent the CRIME attack on SSL and TLS connections.
Test your SSL configuration after applying these settings. Using the openssl command checks whether TLS 1.2 is working correctly.
openssl s_client -connect yourdomain.co.uk:443 -tls1_2
If the handshake succeeds, TLS 1.2 is active. If it fails, review the configuration and check for conflicts with other SSL settings.
Enable Security Headers
HTTP security headers instruct browsers to apply additional protections when loading your pages. These headers do not replace application-level security measures, but they close off entire categories of client-side attack with minimal configuration effort. The headers directive must be enabled first on Debian and Ubuntu systems.
a2enmod headers
Then add these headers to your httpd.conf or an included configuration file.
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
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=()"
X-Content-Type-Options: nosniff prevents the browser from guessing MIME types for scripts and stylesheets, which blocks some content-sniffing attacks. X-Frame-Options: DENY stops your site from being embedded in iframes on other domains, which prevents clickjacking attacks.
X-XSS-Protection enables the browser's built-in XSS filter. Modern browsers handle XSS protection well, so this header is becoming less critical as browser populations update. Referrer-Policy: strict-origin-when-cross-origin controls how much referrer information is shared when visitors navigate away from your site, providing a reasonable balance between functionality and privacy.
Permissions-Policy disables browser features such as geolocation, microphone, and camera access that most websites do not need. If your application uses any of these features, allow them only for the specific paths that require them rather than enabling them globally.
Content Security Policy Header
The Content-Security-Policy header is the most powerful security header available, but it is also the most likely to break functionality if configured incorrectly. CSP tells the browser exactly which content sources are allowed to load and execute on each page. A strict CSP makes cross-site scripting attacks significantly harder to exploit because injected scripts cannot execute.
The safest approach is to start with a report-only header, which monitors what would be blocked without actually enforcing the policy.
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; report-uri /csp-violation-report"
Monitor the violation reports for a period, update the policy based on what your application actually needs, then switch to the enforced header when you are confident the policy is correct.
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; report-uri /csp-violation-report"
The most common mistake with CSP is using 'unsafe-inline' for scripts because it is easier than fixing inline event handlers. Every inline script is a potential XSS vector. Fix the underlying code properly rather than weakening the protection that CSP provides.
Directory and File Access Controls
The <Directory> blocks in httpd.conf control what Apache will serve and what it will allow access to. The default configuration often permits access to paths outside the web root, which becomes dangerous if a path traversal vulnerability exists in your application.
Start with a global deny, then explicitly allow only the paths that need to be served.
<Directory />
Require all denied
</Directory>
Then grant access to the web root specifically.
<Directory /var/www/html>
Require all granted
Options -Indexes -FollowSymLinks
AllowOverride None
</Directory>
Options -Indexes disables directory listing, which prevents attackers from browsing your file structure when an index file is missing. Options -FollowSymLinks stops Apache from following symbolic links, which could otherwise allow access to files outside the web root if a malicious symlink exists. AllowOverride None prevents .htaccess files from modifying Apache behaviour, which simplifies auditing and improves both security and performance.
mod_security Web Application Firewall
mod_security acts as a Web Application Firewall for Apache. It inspects incoming requests against rules and blocks ones that match known attack patterns. On Debian and Ubuntu, enable the module and install the OWASP Core Rule Set for comprehensive coverage.
a2enmod security2
apt install modsecurity-crs
Configure mod_security to inspect requests and load the rule set.
SecRuleEngine On
SecRequestBodyAccess On
SecPcreMatchLimit 1000
SecPcreMatchLimitRecursion 1000
Include /usr/share/modsecurity-crs/crs-setup.conf
Include /usr/share/modsecurity-crs/rules/*.conf
SecRequestBodyAccess On tells mod_security to inspect request bodies, which is necessary for catching attacks in POST requests, form submissions, and JSON payloads. The SecPcreMatchLimit settings prevent regular expression denial of service attacks against the rule engine itself.
Pairing mod_security with Fail2Ban for brute force protection adds another layer of defence against automated attacks targeting your web server.
Timeouts Configuration
Default Apache timeouts are often set too loosely, which can allow slow-read attacks and resource exhaustion from connections that stay open without doing anything useful. Tighten these values based on what your application actually needs.
Timeout 60
KeepAliveTimeout 5
Header unset Connection
Timeout is the maximum seconds Apache waits for a client to send a request and receive a response. For most web applications, 60 seconds is more than sufficient. KeepAliveTimeout controls how long Apache waits for another request on a keep-alive connection before closing it. Setting it to 5 prevents idle connections from consuming server resources unnecessarily.
Limit Request Size and Fields
Prevent oversized requests from consuming server resources or enabling denial of service attacks through large uploads or excessive headers.
LimitRequestBody 10485760
LimitRequestFields 100
LimitRequestFieldSize 8190
LimitRequestBody restricts POST request bodies to 10MB, which is reasonable for most web applications while preventing attackers from uploading extremely large files. LimitRequestFields limits HTTP header fields to 100, which stops attacks that send thousands of headers to exhaust server memory. LimitRequestFieldSize limits the size of each individual header field.
Security-Focused Logging
Logging should capture enough detail to reconstruct attack attempts without generating so much data that logs become unusable. Configure separate error and access logs for security-relevant events.
ErrorLog ${APACHE_LOG_DIR}/error-secure.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access-secure.log combined
Review these logs regularly for patterns. Repeated 403 or 404 responses to unusual URLs, requests with suspicious query strings, and connections from the same IP in quick succession are all worth investigating.
A simple monitoring script that alerts you to failed authentication attempts provides useful early warning without requiring complex tooling.
#!/bin/bash
# Simple failed-auth alert from Apache error log
grep "client denied" /var/log/apache2/error.log | tail -20 | mail -s "Apache Auth Failures" [email protected]
How to Test After Making Changes
Always test the configuration syntax before restarting Apache. A syntax error can prevent the server from starting, which causes unnecessary downtime.
apache2ctl configtest
If the syntax check passes, reload Apache to apply the changes without dropping active connections.
systemctl reload apache2
On RHEL and CentOS, use the equivalent commands.
httpd -t
systemctl reload httpd
After reloading, verify that headers are being sent correctly.
curl -I https://yourdomain.co.uk
Check that security headers appear in the response and that the Server header shows only "Apache" without version information. If the expected headers are missing, the Headers directive may not be loaded or the configuration may have a syntax error.
Common Configuration Mistakes That Create Risk
Several misconfigurations appear repeatedly in Apache installations that have security issues.
- Leaving AllowOverride enabled globally. When
AllowOverrideis set toAllin the root directory, .htaccess files can modify Apache behaviour on a per-directory basis. This makes auditing difficult and can introduce security flaws that are invisible at the global config level. - Not disabling SSLv3. POODLE is a known vulnerability in SSLv3. If your
SSLProtocolline includes+SSLv3, remove it immediately. SSLv3 should never be enabled on a public-facing webserver. - Using self-signed certificates in production. Self-signed certificates break certificate chain validation and make man-in-the-middle attacks possible. Use Let's Encrypt for free, automated certificates that are trusted by all modern browsers and operating systems.
- Avoiding CSP because it seems complicated. A basic CSP that restricts scripts to self is better than no CSP. Start simple and expand as you learn what your application needs.
- Leaving server information in HTTP headers. The
ServerTokensandServerSignaturesettings take minutes to configure and remove useful reconnaissance information from every response. There is no good reason to leave them at defaults on a production server.
Hardening Requires Ongoing Attention
Apache hardening is not a one-time task. New attack vectors emerge, browser support for security headers evolves, and configuration best practices change. Tools like the Mozilla SSL Configuration Generator and the OWASP Core Rule Set receive regular updates that reflect current threats.
Set a calendar reminder to review your Apache configuration at least every six months. Check for updated recommendations from trusted sources, and apply them methodically with testing between each change. Security hardening that worked six months ago may not reflect the current best practice.
The settings in this guide represent the baseline that any publicly accessible Apache instance should meet. Beyond that baseline, your hardening should be driven by what your application actually does, what data it handles, and what the consequences of a compromise would be. A server handling sensitive personal data needs more attention than a static informational site.
If you want a practical review of your Apache setup, you can get in touch with details of your current configuration, the platform you use, and any specific security concerns you want to address.