DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

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; 留给不支持它的二进制。