What HTTP/2 changes on Nginx
On Nginx 1.25.1 or newer, turn HTTP/2 on with http2 on; inside the TLS server block, then run nginx -t and reload. Browsers use HTTP/2 only over HTTPS with ALPN. Older Nginx still uses listen 443 ssl http2;. Confirm the response line says HTTP/2.
HTTP/2 carries many streams on one connection and compresses headers with HPACK. HTTP/1.1 usually queues requests on each connection, so a page full of files waits its turn. Multiplexing is the change. It is not a faster disk and not a new bandwidth cap.
Nginx cuts the response into chunks. The default http2_chunk_size is 8k. A much smaller chunk adds overhead. A much larger chunk weakens prioritization because of head-of-line blocking inside the stream. Leave 8k unless you have measured a reason to move it.
One large file still moves at the speed of the link. The protocol helps when the browser asks for CSS, JavaScript, and images together. If the wait is PHP or the database, start with why a website is slow. The edit itself needs root, which VPS hosting includes and shared hosting does not.
Prerequisites before you enable HTTP/2 on Nginx
Three checks come before the directive. ngx_http_v2_module arrived in Nginx 1.9.5 and is not in the binary unless the build used --with-http_v2_module. Run nginx -V and look for that flag. nginx -v prints the version, and the version picks the syntax below.
- Module flag: --with-http_v2_module in the nginx -V output.
- Version: nginx -v, because 1.25.1 changes the syntax.
- TLS: a certificate on port 443, and OpenSSL 1.0.2 or newer for ALPN.
- Ciphers: off the RFC 9113 Appendix A blacklist when ssl_prefer_server_ciphers is on.
Browsers negotiate HTTP/2 only on HTTPS. If the padlock is missing, install an SSL certificate first, then come back to this server block.
Cleartext HTTP/2 is h2c. The embedded variable $http2 is h2 on TLS, h2c on cleartext TCP, or an empty string. Chrome and Firefox will not use h2c, so a port 80 listener does not switch those browsers.
If ssl_prefer_server_ciphers is on, the cipher list must stay off the RFC 9113 Appendix A blacklist. A blacklisted suite fails the handshake. The site looks down even when nginx -t succeeded. Keep TLS at 1.2 or newer.
Delete any spdy token still on a listen line. SPDY support was withdrawn. Leaving spdy beside http2 is a bad listen line, not a fallback.

Enable HTTP/2 in the Nginx server block
On Nginx 1.25.1 and newer, the switch is the http2 directive. It appeared in that version, it defaults to off, and it is valid in the http and server contexts. The module page's example is listen 443 ssl; followed by http2 on; plus the certificate lines.
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
Put those lines in the server block that already has the certificate. Omit the IPv6 listen line if this host has no IPv6 listener. Leave the existing ssl_certificate and ssl_certificate_key lines where they are.
Before 1.25.1, published steps put the flag on the listen line: listen 443 ssl http2; and the same flag on the IPv6 listen line when you have one. A June 2022 community thread and an SSL vendor's steps still show that older form. Use the form that matches nginx -v. Read the warning from nginx -t instead of stacking both forms.
| Nginx | What turns HTTP/2 on | Where it sits |
|---|---|---|
| Before 1.25.1 | listen 443 ssl http2; | On the listen line |
| 1.25.1 and newer | http2 on; | server block, next to listen 443 ssl;. Default is off |
A proxy in front can still speak HTTP/1.1 to your origin while the browser uses HTTP/2 to the proxy. A June 2022 Cloudflare Community thread said that was the usual origin hop then, and that HTTP/2 on Nginx can shorten uncached responses that are many files at once if the proxy uses HTTP/2 to the origin. Confirm the hop you actually control.
- Copy the file you will edit. On a VPS it is often under /etc/nginx/sites-available/ or /etc/nginx/conf.d/, not always the main nginx.conf.
- Add the version-correct lines in the server block that already holds the certificate. Mirror them on the IPv6 listen line when that line exists.
- Run nginx -t. Fix the path it names. A failed test leaves the running config untouched.
- Reload with systemctl reload nginx. A reload is enough. A full restart is not required for this change.
- If nginx -t names a file you cannot place, email support@webji.services. The mailbox is 24/7 in Hindi and English. The office phone is not a support line.
Verify HTTP/2 with DevTools and curl
The proof is the protocol on the response, not the padlock. curl -sI --http2 https://example.com should show HTTP/2 on the status line. If that curl binary was built without HTTP/2, the error is the client. Run the same command from a machine whose curl supports it.
In Chrome or Firefox, open DevTools, choose Network, turn on the Protocol column, and reload. h2 means the browser negotiated HTTP/2. HTTP/1.1 means it did not: no certificate, no ALPN, the directive on the wrong server, or a proxy that still speaks HTTP/1.1.
On the server, $http2 is h2 when that request is HTTP/2 over TLS. An empty value means the request is not HTTP/2. Check the hostname you typed, not a different server block.
HTTP/2 server push and stream limits on Nginx
Do not enable server push as part of turning HTTP/2 on. http2_push, http2_push_preload, and http2_max_concurrent_pushes have been obsolete since Nginx 1.25.1. The module page names early_hints as the replacement for push.
In 1.19.7, several HTTP/2 timeouts moved to core directives. Use keepalive_timeout instead of http2_idle_timeout, keepalive_requests instead of http2_max_requests, large_client_header_buffers instead of http2_max_field_size and http2_max_header_size, and client_header_timeout instead of http2_recv_timeout.
http2_max_concurrent_streams still applies. The default is 128 streams on one connection. http2_body_preread_size defaults to 64k and appeared in 1.11.0. http2_recv_buffer_size defaults to 256k and is legal only in the http context.
Frequently Asked Questions
How do I enable HTTP/2 in Nginx?
On Nginx 1.25.1 or newer, put http2 on; in the TLS server block, run nginx -t, and reload. On older Nginx, use listen 443 ssl http2;. nginx -V must show --with-http_v2_module.
Does HTTP/2 require HTTPS?
Browsers negotiate HTTP/2 only over TLS with ALPN, which needs OpenSSL 1.0.2 or newer. Cleartext h2c exists, but Chrome and Firefox will not use it. Keep the certificate on port 443.
How do I check if HTTP/2 is enabled?
curl -sI --http2 https://your-domain should report HTTP/2. In DevTools, the Protocol column should read h2. On Nginx, the variable $http2 is h2 for HTTP/2 over TLS.
Should I enable HTTP/2 on Nginx?
Enable it when the site is already HTTPS and the Nginx build includes the module. Pages with many files gain multiplexed streams. A single large download does not get a higher speed cap. Run nginx -t before you reload.
Why does the HTTP/2 handshake fail on Nginx?
A cipher on the RFC 9113 Appendix A blacklist, with ssl_prefer_server_ciphers on, fails the handshake. A leftover spdy flag on listen does the same kind of damage. The directive on a server block that has no certificate never negotiates. nginx -t can still pass.
Does http2 on enable HTTP/3?
HTTP/3 is a separate protocol. The http2 on; directive does not turn it on. Set HTTP/2 first and treat HTTP/3 as its own change after you know the build supports it.

