Nginx 配置 http2 on 后报 unknown directive "http2"
独立 http2 指令从 Nginx 1.25.1 开始提供。核对实际运行版本和 HTTP/2 模块,按旧版兼容语法或升级后的配置处理,并在重载前验证。
更新站点模板后,配置检查在 http2 on; 这一行失败:
nginx: [emerg] unknown directive "http2" in /etc/nginx/conf.d/site.conf:7
nginx: configuration file /etc/nginx/nginx.conf test failed
本机能通过,服务器却失败,常见条件是两端 Nginx 版本不同。独立的 http2 on; 指令从 Nginx 1.25.1 才开始提供;1.19.x、1.24.x 等更早的上游版本即使支持 HTTP/2,也不认识这条新指令。另一个需要排除的条件是当前二进制没有编入 HTTP/2 模块。
这个错误发生在读取配置时。修改浏览器设置、证书内容或防火墙规则,不能让旧程序认识新语法。
查出实际检查配置的程序
在报错的服务器或容器内,使用服务实际调用的 Nginx 可执行文件检查。下面假设路径是 /usr/sbin/nginx;如果启动配置使用其他路径,全部替换为那个路径:
/usr/sbin/nginx -v
/usr/sbin/nginx -V
sudo /usr/sbin/nginx -t
小写 -v 显示版本,大写 -V 还显示编译参数。查看是否包含 --with-http_v2_module。只看开发机的输出没有用;容器运行的服务也不能拿宿主机的 Nginx 版本代替。
配置检查也要使用与服务相同的主配置。若服务通过 -c 指定了文件,检查时带上相同参数;若使用自定义路径前缀,也保留对应的 -p。错误提示中的文件名和行号能定位到实际读取的位置,避免编辑另一份未加载的配置。
根据版本和模块选择处理方式:
- 版本低于 1.25.1,已包含 HTTP/2 模块: 新语法与旧程序不匹配,可以恢复旧语法,或安排升级。
- 版本达到 1.25.1,但编译参数没有 HTTP/2 模块: 单纯改成旧写法也无法补上模块,需要换成包含该模块的构建。
- 版本和模块都符合,仍提示 unknown directive: 对照失败任务的可执行路径、容器与配置参数,确认刚查到的确实是执行失败检查的那套程序。定制发行版还需核对自身的补丁与构建说明。
旧版本先恢复兼容写法
如果只是模板更新,而运行程序暂时不能升级,在原来的 HTTPS server 块中移除独立 http2 on;,把 http2 放回需要启用 HTTP/2 的 listen 行。
下面是完整的示例站点块,放在主配置的 http 上下文内,或已由它包含的站点文件中。域名和证书路径均需替换为已有站点的真实值;实际修改只调整监听与 HTTP/2 设置,保留原有业务路由和安全配置:
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/nginx/certs/app.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/app.example.com/privkey.pem;
location / {
return 200 "ok\n";
}
}
这套写法适用于包含 HTTP/2 模块的旧版 Nginx,listen 的 http2 参数从 1.9.5 开始提供。它用于恢复旧环境的兼容性,不代表应长期停留在已经缺少安全维护的版本。
如果站点原本还有 IPv6 监听,同样检查那条监听的 HTTP/2 参数,并保留原地址、端口及其他必要参数。不要复制示例后额外建立一个重复的监听块,也不要只为绕开报错删除 TLS 设置。
将 http2 on; 改成 http2 off; 无法解决旧版本的未知指令错误:程序仍然需要先认识 http2 这个指令名。若确实决定暂时不用 HTTP/2,应删除独立指令,并让对应监听不再带 http2 参数,同时评估依赖 HTTP/2 的客户端或业务是否还能工作。
升级后的配置使用独立指令
希望继续沿用新模板时,升级目标必须同时满足版本与模块条件。1.25.1 是这条语法的引入版本,不是建议安装的固定版本;选择适合当前系统、仍受维护且经过本地验证的软件包或镜像。
升级前保留现有软件包或镜像版本、配置、证书挂载及服务启动参数。通过当前部署使用的软件源或镜像发布流程升级,避免为了一个语法错误混装另一套 Nginx。单纯重新下载模板不会升级服务器中的程序。
支持新指令的 HTTPS 站点可以采用下面的写法:
server {
listen 443 ssl;
server_name app.example.com;
http2 on;
ssl_certificate /etc/nginx/certs/app.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/app.example.com/privkey.pem;
location / {
return 200 "ok\n";
}
}
http2 指令允许出现在 http 或 server 上下文中。新版本若提示 the "listen ... http2" directive is deprecated,说明遇到的是旧参数弃用警告,应迁移到独立指令;这与旧版本直接拒绝新指令是两个不同的版本方向。
模板由自动化工具生成时,还应同步修改模板或版本条件。只编辑生成后的文件,下次部署可能再次写入不兼容的语法。
检查通过后再加载
先备份要修改的配置,在对应环境完成语法检查。仅修改配置、服务仍正常运行,且采用上述默认路径与主配置时,可以按顺序执行:
sudo /usr/sbin/nginx -t && sudo /usr/sbin/nginx -s reload
&& 确保检查失败时不会继续发送重载信号。使用自定义主配置或前缀时,两条命令都要带相同参数;使用服务管理器的部署应按既有管理方式加载。若刚替换过软件包或容器镜像,还需按部署流程让新程序实际运行,不能把重载配置当作二进制升级。
确认检查不再报未知指令、加载过程没有新的错误,并打开站点检查正常响应。需要验证 HTTP/2 时,可查看浏览器网络面板中的协议结果是否为 h2。如果域名前面还有 CDN 或其他代理,这只能证明浏览器到该入口的协议;应另行检查直接连接目标 Nginx 的结果,不能据此认定源站也启用了 HTTP/2。
配置重载失败时,Nginx 主进程会保留旧配置继续工作;这不表示磁盘上的新配置已经正确。恢复备份后再次检查,避免下一次启动读到坏配置。若升级后需要回退程序,应一并恢复与旧版本匹配的配置,尤其不要把 http2 on; 留给不支持它的二进制。


