How can I make a HTTP/3 connection work with chrome?

1. Caddy version (caddy version):

immo@Ideapad:~$ docker run caddy caddy version
v2.0.0 h1:pQSaIJGFluFvu8KDGDODV8u4/QRED/OPyIR+MWYYse8=

2. How I run Caddy:

a. System environment:

Chromium Version: Version 81.0.4044.138 (Official Build) snap (64-bit)

immo@Ideapad:~$ docker version
Version: 18.09.9
API version: 1.39
Go version: go1.13.4
Git commit: 1752eb3
Built: Sat Nov 16 01:05:26 2019
OS/Arch: linux/amd64
Experimental: false

Version: 18.09.9
API version: 1.39 (minimum version 1.12)
Go version: go1.13.4
Git commit: 9552f2b
Built: Sat Nov 16 01:07:48 2019
OS/Arch: linux/amd64
Experimental: false

Linux Ideapad 5.3.0-51-generic #44-Ubuntu SMP Wed Apr 22 21:09:44 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

b. Command:

docker run -d -p 80:80 -p 443:443 \
-v /immo/home/education/thesis/caddy/Caddyfile:/etc/caddy/Caddyfile  \
-v /immo/home/education/thesis/caddy/certs:/etc/caddy/certs \
-v /immo/home/education/thesis/www:/usr/share/caddy

chromium --enable-quic --quic-version="h3-27" https://localhost/index.html

c. Service/unit/compose file:


d. My complete Caddyfile or JSON config:


localhost {
    root * /usr/share/caddy/
	encode zstd gzip
    tls /etc/caddy/certs/localhost.crt /etc/caddy/certs/localhost.key

3. The problem I’m having:

I’ve been trying to set up a webserver on localhost which supports HTTP/3. I’ve successfully run a caddy server run in docker which answers to GET requests with this header:

alt-svc: h3-27=":443"; ma=2592000
content-encoding: gzip
content-length: 1521
content-type: text/html; charset=utf-8
date: Thu, 07 May 2020 07:27:44 GMT
server: Caddy
status: 200
vary: Accept-Encoding
X-DNS-Prefetch-Control: off

Even though the alt-scv header was received I couldn’t detect any h3-27 requests in the network logs of the developer tools.

I also created a CA, which I added to chrome, and signed the certificate of the server which Chrome accepts.

What am I missing?

4. Error messages and/or full log output:


5. What I already tried:

Using Firefox Nightly instead

6. Links to relevant resources:

FYI, in the the v2 docker image, the storage directories are /data and /config. You should probably persist those as well to prevent data loss from container restarts.

I’m not certain about the h3 issue though, I’ll let someone else help if they can.


Thank you!

HTTP3 (and QUIC) is a black box, to me. Even more so than systemd is. Doesn’t it need exactly the same version on client and server, like, while it’s in draft and changing every now and again?

1 Like

On macOS, I was able to get HTTP/3 working in Chrome Canary Version 84.0.4138.0 (Official Build) canary (64-bit) with the following command: /Applications/Google\ Chrome\\ Chrome\ Canary --enable-quic --quic-version=h3-27

It took a reload of the site though, on first load it was only serving HTTP2.

I’m not sure whether Chrome stable supports the required QUIC version, and I’m not sure about Chromium.


Thanks for all the answers!

Yeah that’s how it should be, since Chrome has to discover the alt-scv header first. builds a H3 connection with Firefox Nightly on my system aswell. But it doesn’t build one with my local caddy server.

At least the Chrome failure may result partly from a version negotiation failure.

@skyfaller May I ask for some configuration details from your server? ( It would really help me a lot, since it is quite urgent for me to get that server running. Thanks in advance!

Well, you may not want to steal my config, since I’m having trouble with my local CA at the moment :slight_smile: But my public sites are running fine, so if you have a public domain name available, stealing my config should work.

All of the server config responsible for producing (and a few other test sites) is available on Github in this Ansible role. Specifically you can see my production Caddyfile (in the form of a Jinja2 template that replaces a couple of variables) here: devops/Caddyfile.j2 at master · sunrisemovement/devops · GitHub

UPDATE: Actually it’s possible that the Caddy storage for my production server is currently misconfigured as well, it just hasn’t caused obvious problems yet. But simply leaving out the storage directive in my Caddyfile and using the default storage location (as you do in your Caddyfile) should be sufficient to avoid that issue.

1 Like

It works for me now with an actual domain and a Let’s Encrypt certificate. If somebody knows, how to make it work on localhost without a domain, i’d really be interested in that. Thank you @skyfaller for your configs, helped me a lot. And thanks for the great support!

1 Like

OK, my local CA is now working, although the steps I took to get there were a little sloppy so I can’t guarantee that everything I did is captured in my Github repo. Still, you can see my test Caddyfile using my local CA at devops/LocalCaddyfile.j2 at master · sunrisemovement/devops · GitHub


1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.