Secure Tengine with security headers
2026-09-29
Your site may be functionally perfect and still score badly on security checkers like SecurityHeaders.com or the Mozilla Observatory — usually because of missing HTTP response headers. These headers cost nothing, break nothing for normal visitors, and harden your site against common web attacks. Here is the block I add to every Tengine server.
The header block
server {
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
What each one does:
X-Frame-Options: SAMEORIGIN— blocks your pages from being embedded in other sites’ iframes (clickjacking)X-Content-Type-Options: nosniff— stops browsers from guessing file types (MIME sniffing)Referrer-Policy— limits how much of your URL leaks as a referrerPermissions-Policy— disables camera/mic/geolocation in the browser for your originHSTS— forces HTTPS for a year; only add this after HTTPS is working reliably, or users get stuck
Two important notes
- The
alwayskeyword matters. Without it, Nginx-family servers only send headers on 2xx responses;alwayssends them on errors and redirects too. - Inheritance gotcha. If you add
add_headerat theserverlevel and then add anotheradd_headerin alocation, the location block replaces the server-level headers for that location instead of adding to them. Either put all headers in one place, or repeat the full set in the location.
Verify with curl
curl -I https://yourdomain.com/
You should see all five headers in the response. Then re-run a header checker and watch the score jump.
Summary
Five lines of headers close the most common web-hygiene gaps, and the always keyword plus single-level placement are the two details that make them actually work. Since you are locking things down, my rate limiting guide handles the brute-force side of the same job.