Essentials

The Security Headers Starter Set (Copy-Paste for Any Server)

4 min · updated June 14, 2026

A solid baseline for almost any site: HSTS, no MIME sniffing, no framing, a tight referrer policy, and locked-down browser features. (Content-Security-Policy is the one header you must tune per site — see the CSP recipe — so it’s noted but not forced on here.)

Nginx

In your server { } block. The always flag matters (sends on error responses too):

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
# add_header Content-Security-Policy "default-src 'self'" always;  # tune first — see CSP recipe

Nginx gotcha: if a location block has its own add_header, it drops all inherited ones. Repeat the headers there, or set them once at server level with no add_header inside locations.

Apache (mod_headers)

In the vhost or .htaccess (needs a2enmod headers):

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=()"

Caddy (v2)

Inside the site block:

header {
    Strict-Transport-Security "max-age=31536000; includeSubDomains"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "strict-origin-when-cross-origin"
    Permissions-Policy "geolocation=(), camera=(), microphone=()"
}

Cloudflare Pages / Netlify (_headers)

A _headers file at the site root:

/*
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  X-Content-Type-Options: nosniff
  X-Frame-Options: SAMEORIGIN
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: geolocation=(), camera=(), microphone=()

Verify

curl -sI https://yourdomain.com | grep -iE 'strict-transport|x-content-type|x-frame|referrer-policy|permissions-policy'

Before HSTS in production: make sure HTTPS works on every subdomain first — includeSubDomains forces them all onto HTTPS, and HSTS is cached by browsers for the full max-age. See the HSTS recipe for preload and the rollback caveats.

← All recipes