Blitz electric_bolt

Set up HTTP/3 in NGINX reverse proxy

Introducing Blitz posts this Christmas: concise guides, straight to the point!

info

Note

This guide will use the HTTPS port (443), but you can apply this to any port you want.

Step 1: Edit .conf file

If you’ve enabled HTTP/2 on NGINX, your website configuration should look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server {
    listen 443 ssl;
    http2 on;
    server_name tavern.edotm.net;
    
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        # ...
    }
}

If you’ve installed NGINX in Docker, its version should be 1.25.x or greater. In that case, add the following highlighted lines:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
server {
    listen 443 ssl;
    listen 443 quic reuseport;
    http3 on;
    http2 on;
    server_name tavern.edotm.net;
    
    add_header Alt-Svc 'h3=":443"; ma=86400';
    
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        # ...
    }
}

These lines should activate HTTP/3 for you! Alternatively, if you share the same configuration among different files, simplify them by adding these lines to the main nginx.conf:

http {
  # ...
  http2 on;
  http3 on;
  quic_retry on;
  ssl_early_data on;
  quic_gso on;
  add_header Alt-Svc 'h3=":443"; ma=86400';
  # ...
}

so that your .conf files will look a lot simpler:

1
2
3
4
5
6
7
8
9
server {
    listen 443 ssl;
    listen 443 quic reuseport;
    server_name tavern.edotm.net;

    location / {
        # ...
    }
}
What are quic_retry, quic_gso, etc.?

They are additional options for QUIC. See all the available options and their documentation here.

info

Note

For me, the quic_bpf directive mentioned in the documentation was not working.

Wait, it is giving me an error like “duplicate listen options for…”

This is common if you have multiple files handling different subdomains (e.g., one for gitlab.site.com, one for blog.site.com, etc.).

The reason for this error is that you have two different .conf files, both with listen ... quic reuseport. The reuseport part must only appear once (per IP address).

To solve this, put the reuseport only in the main subdomain (www.site.com or site.com). The other subdomains should only have

listen 443 ssl;  # for HTTPS, optional
listen 443 quic; # without `reuseport`

Don’t worry, HTTP/3 will also work for the other subdomains!

Step 2: Open UDP ports

Since HTTP/3 uses the QUIC protocol based on UDP, take these steps:

  1. Forward port 443 UDP in your router’s configuration.
  2. Allow port 443 UDP from the server’s firewall.

For the first part, add a rule in the router configuration page for your server’s internal IP. For the second part, if you have Fedora Server do:

sudo firewall-cmd --add-port=443/udp --permanent

Or, if you use ufw:

sudo ufw allow 443/udp

Step 3: Map port in Docker

For NGINX in Docker, change the ports section on NGINX’s docker-compose.yml file from this:

ports:
  - "443:443"

to this:

ports:
  - "443:443/tcp"
  - "443:443/udp"
info

Note

Remember, you can apply this to other ports. Do this for all the ports you want to activate HTTP/3.

Now, benefit

Your site should now have HTTP/3 up and running!