最稳妥的方式是在每个HTTPS的server块中用include引入安全头文件。需创建独立目录存放带always参数的通用头文件,按站点粒度引入,避免http块全局配置导致HSTS误启或CSP白屏,且HSTS和CSP必须按站点定制。

直接在每个 HTTPS 的 server 块里写 add_header ... always; 是最稳妥的方式。但当站点数量多(比如十几个或几十个),逐个手动复制粘贴容易出错、难维护。用 include 拆分配置,既能批量复用安全头,又能保持各站点独立可控。
核心思路是:把通用安全头抽成独立文件,再在每个站点的 server 块中用 include 引入
✅ 正确做法:按站点粒度 include 安全头文件
Nginx 不支持在 http 块顶层统一加 add_header 并让所有 server 继承——因为 add_header 的作用域只限于当前块及其子块,且若放在 http 层,会作用于所有响应(包括 HTTP 站点),可能误启 HSTS 或触发 CSP 白屏。
所以你应该:
- 创建一个专门存放安全头的目录,例如
/www/server/nginx/conf/secure-headers/ - 为不同策略建不同文件(可选):
-
basic-headers.conf(基础防护头) -
hsts-strict.conf(含includeSubDomains的 HSTS) -
csp-report-only.conf(CSP 报告模式)
-
- 在每个 HTTPS 站点的
server块内,紧贴 SSL 配置下方include对应文件
示例(宝塔用户路径类似):
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# ✅ 正确引入:仅对该站点生效
include /www/server/nginx/conf/secure-headers/basic-headers.conf;
include /www/server/nginx/conf/secure-headers/hsts-strict.conf;
location / {
root /www/wwwroot/example.com;
index index.html;
}
}basic-headers.conf 内容示例(务必带 always):
add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
⚠️ 注意事项:避免常见坑
always参数不能省
否则 404、500、302 页面不会携带这些头,攻击面实际没收窄。-
HSTS 和 CSP 必须按站点定制
-
Strict-Transport-Security中的includeSubDomains只对当前server_name生效;主站启用后,子站若走独立证书或 CDN,必须单独验证 HTTPS 可用后再加,否则会锁死非 HTTPS 访问。 -
Content-Security-Policy不能通用:嵌了 YouTube 就得加frame-src youtube.com;,用了 Google Fonts 就要加font-src fonts.gstatic.com;。建议先用Content-Security-Policy-Report-Only观察日志两周,再切正式模式。
-
不要 include 到 http 块或 location 外层通用区
include必须放在具体server块内部,且最好在ssl_certificate之后、location之前,确保它属于该 HTTPS 上下文。宝塔用户可免手改(2026年已支持)
在站点设置 → SSL → 配置文件 → “自定义头部” 中勾选“对所有状态码生效”,面板会自动注入带always的add_header,并隔离到当前站点配置中。
? 批量管理建议(运维友好)
- 把
secure-headers/目录纳入 Git 版本控制,每次更新头策略时提交、审核、灰度上线。 - 对新站点,只需复制模板
server块 + 一行include,无需重复写十几行头。 - 配合 Ansible 或 Shell 脚本,自动为所有
.conf文件插入指定include行(注意跳过 HTTP 站点)。
不复杂但容易忽略。


















