By server

All Security Headers for Apache (mod_headers)

3 min read

A complete Apache baseline using mod_headers. First enable the module:

sudo a2enmod headers

Then paste into your <VirtualHost> (preferred) or .htaccess:

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 "geolocation=(), camera=(), microphone=()"
Header always set Cross-Origin-Opener-Policy "same-origin"
# Tune CSP per site — start report-only (see the CSP recipe):
Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"

# Reduce fingerprinting:
Header always unset X-Powered-By

Trim the Server header in the main server config (not .htaccess):

ServerTokens Prod
ServerSignature Off

set vs always set

Plain Header set only applies to successful (2xx) responses; Header always set also covers error responses (4xx/5xx). Use always for security headers.

Test and reload

sudo apachectl configtest && sudo systemctl reload apache2

Verify

curl -sI https://yourdomain.com
curl -sI https://yourdomain.com/nonexistent

.htaccess only works if AllowOverride permits it and the directory is served by Apache — vhost config is faster and not per-request, so prefer it when you control the server.

Open the full version (with copy buttons) ↗

← All recipes