Nginx启用HSTS必须在443端口HTTPS server块中配置add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always,确保非2xx响应也生效;includeSubDomains要求所有子域HTTPS可用,preload需满足全站HTTPS、含子域且max-age≥1年等硬性条件,上线前须灰度验证并屏蔽后端HSTS头。

要在 Nginx 中真正启用 HSTS 并发挥其强制 HTTPS 的作用,不能只加一行头就完事。关键在于配置位置、参数取值、生效范围和上线节奏——稍有疏忽,可能让子域名无法访问,或导致测试环境被浏览器永久拦截。
必须放在 HTTPS server 块里
HSTS 头只应在监听 443 端口、启用 SSL 的 server 块中添加。如果错放在 HTTP(80 端口)块里,浏览器会直接忽略该头;更严重的是,若后端应用(如 Spring Boot、Node.js)自己返回了 HSTS,而 Nginx 又没做清理,会出现策略冲突。
- 正确写法示例:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
-
always参数不可省略:确保 304、404、500 等非 2xx 响应也携带 HSTS 头,避免因缓存或错误中断策略传递 - 不要在
http或location块顶层全局添加,易被覆盖或误生效
includeSubDomains 要求严格验证
启用 includeSubDomains 意味着所有子域名(如 api.example.com、blog.example.com)都必须支持 HTTPS 且证书有效。否则用户访问任一子域名失败,整个主域可能被浏览器标记为“不安全”并拒绝加载。
- 上线前逐个检查:
curl -I https://sub.example.com,确认返回 200 且无证书警告 - 检查 Nginx 错误日志,搜索
ssl_handshake_failed或no suitable certificate - 若暂未全量覆盖 HTTPS 子域,先去掉
includeSubDomains,仅对主站生效
preload 参数需满足硬性条件
加上 preload 是为了让网站进入 Chrome、Firefox、Safari 的 HSTS 预加载列表,实现“首次访问即强制 HTTPS”。但提交前必须满足:
- 主域名必须通过 HTTPS 返回 HSTS 头,且
max-age ≥ 31536000(1 年) - 必须包含
includeSubDomains - 所有子域名必须可 HTTPS 访问,且响应头中同样含完整 HSTS 策略
- 建议先用
max-age=300(5 分钟)灰度上线 15 分钟,确认无跳转异常、混合内容或证书问题后再调高
反向代理场景要隐藏后端 HSTS
当 Nginx 前置代理后端服务(如 Java 或 Python 应用)时,后端常自带 HSTS 响应头。此时需主动屏蔽,避免策略混乱:
- 在对应
location块中添加:proxy_hide_header Strict-Transport-Security; - 再由 Nginx 统一通过
add_header注入,确保策略唯一、可控 - 特别注意测试环境:后端若在 HTTP 下也发 HSTS,浏览器会直接拒绝连接,必须禁用


















