Skip to content

Commit 7554581

Browse files
committed
nixos/h2o: enable HTTP/3 via QUIC
1 parent 301581e commit 7554581

File tree

3 files changed

+61
-16
lines changed

3 files changed

+61
-16
lines changed

nixos/modules/services/web-servers/h2o/default.nix

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,7 @@ let
221221
headerSet ++ [ hsts ];
222222
}
223223
);
224-
in
225-
value.settings
226-
// headerRecAttrs
227-
// {
224+
228225
listen =
229226
let
230227
identity =
@@ -233,17 +230,27 @@ let
233230
key-file = "${certs.${names.cert}.directory}/key.pem";
234231
certificate-file = "${certs.${names.cert}.directory}/fullchain.pem";
235232
};
233+
234+
baseListen =
235+
{
236+
port = port.TLS;
237+
ssl = (lib.recursiveUpdate tlsRecAttrs value.tls.extraSettings) // {
238+
inherit identity;
239+
};
240+
}
241+
// lib.optionalAttrs (value.host != null) {
242+
host = value.host;
243+
};
244+
245+
# QUIC, if used, will duplicate the TLS over TCP directive, but
246+
# append some extra QUIC-related settings
247+
quicListen = lib.optional (value.tls.quic != null) (baseListen // { inherit (value.tls) quic; });
236248
in
237249
{
238-
port = port.TLS;
239-
ssl = (lib.recursiveUpdate tlsRecAttrs value.tls.extraSettings) // {
240-
inherit identity;
241-
};
242-
}
243-
// lib.optionalAttrs (value.host != null) {
244-
host = value.host;
250+
listen = [ baseListen ] ++ quicListen;
245251
};
246-
};
252+
in
253+
value.settings // headerRecAttrs // listen;
247254
};
248255
in
249256
# With a high likelihood of HTTP & ACME challenges being on the same port,

nixos/modules/services/web-servers/h2o/vhost-options.nix

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,25 @@ in
152152
'';
153153
};
154154
recommendations = tlsRecommendationsOption;
155+
quic = mkOption {
156+
type = types.nullOr types.attrs;
157+
default = null;
158+
description = ''
159+
Enables HTTP/3 over QUIC on the UDP port for TLS. The attrset
160+
provides fine-turning for QUIC behavior, but can be empty. See
161+
<https://h2o.examp1e.net/configure/http3_directives.html#quic-attributes>.
162+
'';
163+
example =
164+
literalExpression
165+
# nix
166+
''
167+
{
168+
amp-limit = 2;
169+
handshake-timeout-rtt-multiplier = 300;
170+
retry = "ON";
171+
}
172+
'';
173+
};
155174
extraSettings = mkOption {
156175
type = types.attrs;
157176
default = { };

nixos/tests/web-servers/h2o/basic.nix

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ in
4343
server =
4444
{ pkgs, ... }:
4545
{
46+
environment.systemPackages = [
47+
pkgs.curlHTTP3
48+
];
49+
4650
services.h2o = {
4751
enable = true;
4852
defaultHTTPListenPort = port.HTTP;
@@ -60,6 +64,9 @@ in
6064
"${domain.TLS}" = {
6165
tls = {
6266
policy = "force";
67+
quic = {
68+
retry = "ON";
69+
};
6370
identity = [
6471
{
6572
key-file = ../../common/acme/server/acme.test.key.pem;
@@ -99,10 +106,15 @@ in
99106
];
100107

101108
networking = {
102-
firewall.allowedTCPPorts = with port; [
103-
HTTP
104-
TLS
105-
];
109+
firewall = {
110+
allowedTCPPorts = with port; [
111+
HTTP
112+
TLS
113+
];
114+
allowedUDPPorts = with port; [
115+
TLS
116+
];
117+
};
106118
extraHosts = ''
107119
127.0.0.1 ${domain.HTTP}
108120
127.0.0.1 ${domain.TLS}
@@ -130,6 +142,13 @@ in
130142
131143
assert "${sawatdi_chao_lok}" in server.succeed("curl -v --http2 --tlsv1.3 --compressed --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'")
132144
145+
quic_hello_world_head = server.succeed("curl -v --head --compressed --http3-only --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'").lower()
146+
assert "http/3 200" in quic_hello_world_head
147+
assert "server: h2o" in quic_hello_world_head
148+
assert "content-type: text/x-rst" in quic_hello_world_head
149+
150+
assert "${sawatdi_chao_lok}" in server.succeed("curl -v --http3-only --compressed --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'")
151+
133152
assert "redirected" in server.succeed("curl -v --head --fail-with-body 'http://${domain.TLS}:${portStrHTTP}/hello_world.rst'").lower()
134153
135154
server.fail("curl --location --max-redirs 0 'http://${domain.TLS}:${portStrHTTP}/hello_world.rst'")

0 commit comments

Comments
 (0)