How to add security headers (Nginx, Apache, Cloudflare)

Updated August 2026 · about a 7-minute read

If a scan just told you your site is missing HSTS, a Content-Security-Policy, X-Content-Type-Options or X-Frame-Options, this is the copy-paste fix. Add the safe ones first, test HTTPS before HSTS, and treat CSP with care. Configs for the three most common setups are below.

The headers, in the order to add them

HeaderWhat it stopsRisk of breaking your site
X-Content-Type-OptionsMIME-sniffing attacksNone — add it now
X-Frame-OptionsClickjackingLow (only if you embed yourself)
Referrer-PolicyURL/data leakageNone
Strict-Transport-Security (HSTS)HTTPS downgrade / SSL-stripOnly if HTTPS isn't fully working
Content-Security-PolicyCross-site scripting (XSS)High if untuned — do last

Nginx

Add inside the server { } block (or a shared snippets/ include), then reload:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self'" always;

The always keyword matters — without it, headers are skipped on error responses. Reload with nginx -t && systemctl reload nginx.

Apache

Enable headers (a2enmod headers), then in your vhost or .htaccess:

Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self'"

Cloudflare

No server access needed. Go to your domain → Rules → Transform Rules → Modify Response Header, and add each header with "Set static". Cloudflare applies them at the edge for every response. This is the fastest option if you're on Cloudflare and can't touch the origin.

About HSTS and CSP — the two that bite

HSTS forces browsers to use HTTPS and remembers it. Only add it once your site works fully over HTTPS with no mixed content, or visitors can get locked out. Start with a small max-age, confirm, then raise to 31536000 (a year). Add preload only when you're certain — see what HSTS and preload actually do.

CSP is the most powerful and the most likely to break your own site by blocking scripts and styles. Start in report-only mode, watch what it would block, then tighten. The security headers guide covers a safe rollout.

The part people forget: headers regress

Here's the trap. You add these today, the scan goes green, everyone's happy — and three months later a redeploy, a stack migration, or a new CDN rule silently drops one of them. The site still works, so nobody notices, until a customer's security review flags it. Adding headers is a one-time job; keeping them is continuous. That's the whole reason to monitor: get an email the moment a header that was there disappears.

Confirm your headers landed — then keep them that way

Run your domain to see which headers are present now. Perimeter then re-checks daily and emails you the moment one regresses after a deploy.

Monitor headers continuously → · from $29/mo, no signup to check