为什么要自编译 Nginx?
Ubuntu 默认 apt 源里的 nginx 不支持 HTTP/3(QUIC),
官方仓库里的也不支持,必须:
- 使用 Nginx 1.25+(我用的是 1.27.2)
- 使用 OpenSSL 的 QUIC 分支(QuicTLS)
- 自己编译带 http_v3_module
此外很多人也会顺便编译:
- ngx_brotli(Google Brotli 压缩)
- zstd-nginx-module(Zstandard 压缩)
- headers-more(更灵活控制响应头)
- http_slice_module(针对大文件 Range 分片)
本文全部涵盖。
编译环境准备
1 2 3 4
| sudo apt update sudo apt install -y build-essential git curl wget \ libpcre3 libpcre3-dev zlib1g-dev libxslt1-dev \ libxml2-dev libgd-dev libgeoip-dev libjemalloc-dev
|
下载源码(推荐统一目录)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| mkdir ~/nginx-http3 cd ~/nginx-http3
wget https://nginx.org/download/nginx-1.27.2.tar.gz tar xf nginx-1.27.2.tar.gz
git clone https://github.com/quictls/openssl.git quictls
git clone https://github.com/google/ngx_brotli.git git clone https://github.com/tokers/zstd-nginx-module.git git clone https://github.com/openresty/headers-more-nginx-module.git
cd ngx_brotli git submodule update --init --recursive cd ..
|
此时目录结构应为:
1 2 3 4 5 6
| ~/nginx-http3/ ├── nginx-1.27.2/ ├── quictls/ ├── ngx_brotli/ ├── zstd-nginx-module/ └── headers-more-nginx-module/
|
编译 Nginx + QuicTLS(最关键一步)
进入 nginx 源码目录:
1 2
| cd ~/nginx-http3/nginx-1.27.2 make clean || true
|
执行 configure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_v3_module \ --with-http_slice_module \ --with-pcre-jit \ --with-threads \ --with-file-aio \ --with-http_gzip_static_module \ --with-http_sub_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-http_secure_link_module \ --with-stream \ --with-stream_ssl_module \ --with-stream_realip_module \ --with-stream_ssl_preread_module \ --add-module=../ngx_brotli \ --add-module=../zstd-nginx-module \ --add-module=../headers-more-nginx-module \ --with-openssl=../quictls \ --with-openssl-opt=enable-ktls \ --with-cc-opt='-O2 -fPIC' \ --with-ld-opt='-ljemalloc'
|
编译 + 安装:
1 2
| make -j"$(nproc)" sudo make install
|
验证:
1
| /usr/local/nginx/sbin/nginx -V
|
如果看到:
1 2
| --with-http_v3_module built with OpenSSL 3.x.x+quic
|
则说明成功支持 HTTP/3。
配置 systemd 服务(替代 apt 安装的 nginx)
创建:
1
| sudo nano /etc/systemd/system/nginx-quic.service
|
写入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [Unit] Description=Nginx QUIC (self-built) After=network.target
[Service] Type=forking PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /etc/nginx/nginx.conf ExecStart=/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/local/nginx/sbin/nginx -s quit
[Install] WantedBy=multi-user.target
|
启用:
1 2
| sudo systemctl daemon-reload sudo systemctl enable --now nginx-quic
|
HTTP/3 多域名正确写法(关键)
HTTP/3(QUIC)在 Nginx 的限制:
同一个 IP:443 上,多个 server 块可以同时支持 HTTP/3,但只有一个 server 可以用 reuseport。
其他 server 只能用 listen 443 quic;。
主域名(带 reuseport):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| server { listen 443 ssl; listen [::]:443 ssl; http2 on;
listen 443 quic reuseport; listen [::]:443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400' always; server_name example.com;
}
|
第二个域名(不带 reuseport):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| server { listen 443 ssl; listen [::]:443 ssl; http2 on;
listen 443 quic; listen [::]:443 quic;
add_header Alt-Svc 'h3=":443"; ma=86400' always; server_name example1.com;
root /var/www/music-api; index index.html;
}
|
为什么这样写能让两个域名都支持 HTTP/3?
因为:
- QUIC 的 socket(UDP)只需要一个 reuseport 入口;
- 其余 server 共享该 socket,内部按 TLS SNI 分配给正确的 vhost。
检查 HTTP/3 是否生效
浏览器检查:
- Chrome 地址栏输入:
chrome://net-internals/#http2
- 或 F12 → Network → Protocol
命令行验证:
1
| curl -I --http3-only https://你的域名
|
返回 HTTP/3 表示成功。
踩坑总结
duplicate listen options?
原因:
同一个 IP:443 多次写 listen 443 quic reuseport。
解决:
只有一个 server 支持 reuseport,其余写成:
listen 443 quic;
HTTP/3 访问走错域名?
原因:
你给所有域名都加了 Alt-Svc,但 QUIC 监听只在一个 server。
解决:
按本文的主域名(reuseport)+ 副域名(no reuseport)模式写。