From c4616ab57aff6506579af38d80a3acfe09cacb97 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Wed, 22 Jul 2026 22:53:44 -0500 Subject: [PATCH] http/3 support --- Dockerfile | 3 ++- Overlord-Server/src/main-server.ts | 6 ++++++ README.md | 26 ++++++++++++++++++++++++++ docker-compose.windows.yml | 2 ++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 527b123..e99e1f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -178,7 +178,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ GOMODCACHE=/go/pkg/mod \ go mod download -EXPOSE 5173 +EXPOSE 5173/tcp +EXPOSE 5173/udp ENV PORT=5173 ENV HOST=0.0.0.0 diff --git a/Overlord-Server/src/main-server.ts b/Overlord-Server/src/main-server.ts index 625f413..fde9182 100644 --- a/Overlord-Server/src/main-server.ts +++ b/Overlord-Server/src/main-server.ts @@ -762,6 +762,8 @@ async function startServer() { handleWebSocketMessage, handleWebSocketClose, }), + // HTTP/3 mfs (bun barely supports it but we rocking it) + ...(tls ? { http3: true, http1: true } : {}), }); @@ -830,6 +832,9 @@ async function startServer() { if (tls) { logServerStartup(server, tls.certPathUsed, tls.source); + logger.info( + `[HTTP/3] Enabled (QUIC over UDP port ${server.port}; HTTP/1.1 TCP fallback enabled)`, + ); logger.info(`[HTTP] maxRequestBodySize=${MAX_HTTP_BODY_BYTES} bytes`); } else { const hostname = server.hostname || "0.0.0.0"; @@ -842,6 +847,7 @@ async function startServer() { logger.info(""); logger.info("External access should be HTTPS/WSS via your reverse proxy platform."); logger.info("Set this mode only when TLS is terminated by the platform (for example Render). "); + logger.info("[HTTP/3] Disabled (in-process TLS is offloaded to the reverse proxy)"); logger.info(`[HTTP] maxRequestBodySize=${MAX_HTTP_BODY_BYTES} bytes`); logger.info("========================================"); } diff --git a/README.md b/README.md index 42cffd1..4ee2099 100644 --- a/README.md +++ b/README.md @@ -573,6 +573,32 @@ Overlord can serve HTTP only on loopback while nginx, Caddy, Traefik, IIS, or another trusted reverse proxy owns the public HTTPS certificate. Browsers and agents must still use the public `https://` / `wss://` address. +HTTP/3 is enabled automatically when Overlord terminates TLS itself. QUIC uses +UDP on the same port as HTTPS (5173 by default), so direct deployments must +allow both TCP and UDP on that port. HTTP/1.1 remains enabled for initial +`Alt-Svc` discovery, health checks, clients without HTTP/3, and WebSocket +upgrades. When `OVERLORD_TLS_OFFLOAD=true`, the reverse proxy owns public +HTTP/3 support because Bun's internal listener has no TLS. + +To verify both advertisement and an actual QUIC transfer with an HTTP/3-capable +curl build: + +```powershell +.\scripts\test-http3.ps1 https://YOUR_OVERLORD_HOST:5173/health +``` + +For a self-signed certificate, add `-AllowUntrustedCertificate`. + +To compare cold HTTP/1.1 and HTTP/3 request timings: + +```powershell +.\scripts\benchmark-http3.ps1 https://YOUR_OVERLORD_HOST:5173/health -Requests 30 +``` + +The benchmark selects an HTTP/3-capable curl automatically, validates the +protocol used by every sample, prints average/p50/p95 timing, and saves the raw +measurements as CSV. + For a native install or Linux Docker with host networking, add this to `.env`: ```env diff --git a/docker-compose.windows.yml b/docker-compose.windows.yml index 834201a..c9701bb 100644 --- a/docker-compose.windows.yml +++ b/docker-compose.windows.yml @@ -11,6 +11,8 @@ services: container_name: overlord-server ports: - "${OVERLORD_PUBLISH_HOST:-0.0.0.0}:${PORT:-5173}:5173" + # HTTP/3 uses QUIC over UDP on the same port as HTTPS/TCP. + - "${OVERLORD_PUBLISH_HOST:-0.0.0.0}:${PORT:-5173}:5173/udp" environment: PORT: 5173 HOST: 0.0.0.0