Nginx中HSTS应通过模块化(独立include文件)、变量化(map或Ansible role控制参数)、自动化(GitOps校验+灰度回滚)实现统一部署,确保仅在443 HTTPS server块生效,且支持环境差异化与分钟级回滚。

在 Nginx 中实现 HSTS(HTTP Strict Transport Security)的统一模板化与自动化部署,关键不是给每个 server 块单独加 add_header Strict-Transport-Security,而是把它变成可复用、可验证、可按环境开关的安全策略模块,并通过 Ansible 或 GitOps 流程落地到所有 HTTPS 站点。
把 HSTS 配置抽成独立 include 模块
HSTS 属于通用安全头,应从具体站点配置中剥离,集中定义在全局或 http 块中。推荐做法是:
- 新建文件
/etc/nginx/conf.d/security-hsts.conf,内容为:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
- 在所有启用 HTTPS 的
server块末尾统一include conf.d/security-hsts.conf; - 如需按环境差异化(例如 staging 不启用 preload),可用
map或变量控制:
在 http 块中定义:map $env_name $hsts_value {<br> default "max-age=31536000; includeSubDomains";<br> prod "max-age=31536000; includeSubDomains; preload";<br>}
再在 server 块中写:add_header Strict-Transport-Security $hsts_value always;
Ansible 中用 role + 变量驱动 HSTS 开关
不建议在 playbook 里硬写 add_header 指令。应通过 role 抽象,让 HSTS 成为一个可配置项:
- 在
roles/nginx-security/defaults/main.yml中定义:nginx_hsts_enabled: true<br>nginx_hsts_max_age: 31536000<br>nginx_hsts_include_subdomains: true<br>nginx_hsts_preload: "{{ 'true' if env_name == 'prod' else 'false' }}" - 在
roles/nginx-security/templates/hsts.conf.j2中渲染:
{% if nginx_hsts_enabled %}
add_header Strict-Transport-Security "max-age={{ nginx_hsts_max_age }}; {% if nginx_hsts_include_subdomains %}includeSubDomains; {% endif %}{% if nginx_hsts_preload == 'true' %}preload"{% else %}" always;
{% endif %}
{% endif %} - 部署时只需改 inventory 变量,无需动模板或代码,HSTS 即可随环境自动启停或降级
GitOps 流水线中加入 HSTS 合规性校验
HSTS 不只是“加上就行”,还要确保它只出现在 HTTPS server 块中,且不被低优先级指令覆盖。CI 阶段应做两件事:
- 语法检查后追加静态分析:用
grep -r "Strict-Transport-Security" /tmp/rendered-conf/ | grep -v "https"排查是否误配在 HTTP 块里 - 用 Python 脚本解析生成的配置树,验证所有
server { listen 443 ssl; ... }下都存在且仅存在一条add_header Strict-Transport-Security(避免重复导致 header 覆盖) - 若检测失败,流水线直接中断,不进入 reload 阶段——防止带错误安全策略上线
生产环境灰度与回滚机制
HSTS 的 max-age 一旦生效,浏览器会强制缓存该策略,错误配置可能导致大量用户无法访问。因此必须支持快速回滚:
- Ansible 执行 reload 前,先备份当前生效配置:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.{{ ansible_date_time.iso8601_basic_short }} - 配合健康检查脚本(如 curl -I https://example.com | grep Strict-Transport-Security),确认 header 正确返回后再标记发布成功
- 若发现 header 缺失或值异常,自动触发
git revert+ 重新部署上一版 commit,实现分钟级恢复


















