# โšก Serve HTTP/3 HTTP/3 is enabled by default: an HTTPS site uses a QUIC listener on UDP 443 unless the global protocol list excludes `h3`. Check the response protocol: a client may use HTTP/2 after an HTTP/3 connection fails. ๐Ÿ“Œ This page describes **v0.2.2**. ## ๐Ÿงพ Before you start - A name that resolves to the host, and a certificate for it ([HTTPS](/start/https/)). - **UDP 443 open** in the provider's firewall and the host's. If UDP is blocked, clients may use HTTP/2 instead. - A client with HTTP/3 support. The system `curl` on most distributions does not have it and reports this error: ```text curl: option --http3: the installed libcurl version doesn't support this ``` ## ๐Ÿ”Œ Configure HTTP/3 ```caddyfile { email bonjour@pingclair.com servers { protocols h1 h2 h3 } } example.com { file_server /srv/site } ``` After starting the site, check the UDP listener on the host: ```bash sudo ss -lunp | grep ':443 ' ``` ```text UNCONN 0 0 *:443 *:* users:(("pingclair",pid=5425,fd=22)) ``` Removing `h3` from the list removes the QUIC listener ([TLS: what you can tune](/guides/tls-tuning/#-which-protocols-are-served)). Without a `protocols` line, HTTP/3 remains enabled. The `tls` block also accepts a per-site switch: ```caddyfile example.com { tls { http3 off } file_server /srv/site } ``` `http3 off` refuses this site's QUIC handshake and removes its HTTP/3 advertisement from `Alt-Svc`. Other sites on the port may continue to use QUIC. ## โœ… Verify the client protocol Use an HTTP/3-capable client, such as curl built with ngtcp2 or quiche. If the host's curl lacks HTTP/3 support, use a container: ```bash docker run --rm --network host \ ymuski/curl-http3 curl -sI --http3 https://example.com/ ``` ```text curl 8.2.1-DEV (x86_64-pc-linux-gnu) libcurl/8.2.1-DEV BoringSSL zlib/1.2.13 nghttp2/1.52.0 quiche/0.18.0 ``` `--network host` lets the container use the host's network directly. Without it, the request may pass through a network namespace that blocks QUIC. ```text HTTP/3 200 content-type: text/html; charset=utf-8 etag: "5e-6ab20622" accept-ranges: bytes x-served-by: pingclair server: Pingclair ``` The `HTTP/3` status line confirms the protocol used for this response. Requesting the same URL with `--http2` and `--http1.1` shows the other two protocols, which confirms that the client is not falling back. When a container is not available, a QUIC handshake can be checked with the system's OpenSSL, if it is 3.5 or newer: ```bash openssl s_client -quic -alpn h3 -connect example.com:443 -servername example.com ## โš ๏ธ Troubleshooting - **`option --http3: the installed libcurl version doesn't support this`.** The client has no HTTP/3; use a container as above. - **`curl --http3` does not complete or times out.** UDP 443 may be blocked. Check the provider's firewall or security group first, then the host's. - **No UDP listener on the host.** `h3` is missing from the `servers` protocol list, or the file that is running is not the one you edited ([what a reload means](/start/service/#-what-a-reload-means)). - **HTTP/3 works locally and not from outside.** The client's network may block UDP 443; browsers may use HTTP/2 instead. ## ๐Ÿงญ Next steps - [TLS: what you can tune](/guides/tls-tuning/): the protocol list, certificates, and client certificates. - [Project status](/project/status/): what is supported, refused, and affected by known defects in this release. - [`tls`](/reference/directives/#tls): the `http3` option in context.