From a331b85dc3a3ea8ae50d4124ed01e19404fdcecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 29 Aug 2026 22:19:31 +0100 Subject: [PATCH] a host that predates HTTP/2 can be repaired MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `http2_support: true` is the default now and is set when a host is secured, but both hosts here were created and secured before either change, so nothing re-runs and they stay on HTTP/1.1 forever. Lighthouse costs that 670 ms. An explicit action rather than a fix applied on load: a panel that silently rewrites the proxy while somebody is reading it is not a thing to build, and the change reloads nginx for every site behind it. Only offered where it can do something — a host with a certificate that lacks it. HTTP/2 is negotiated during the TLS handshake, so on a plain host the field is stored and never used, and the button would do nothing visible. A host created since the default never shows it: this is a repair, not a setting. Co-Authored-By: Claude Opus 5 (1M context) --- web/ProxiesBlock.tsx | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/web/ProxiesBlock.tsx b/web/ProxiesBlock.tsx index 7677813..af32f9d 100644 --- a/web/ProxiesBlock.tsx +++ b/web/ProxiesBlock.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef, useState } from 'react'; -import { CircleDot, Globe, Loader2, Lock, Plus, ShieldCheck } from 'lucide-react'; +import { CircleDot, Gauge, Globe, Loader2, Lock, Plus, ShieldCheck } from 'lucide-react'; import { useClient } from 'hooks/useClient'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; @@ -46,6 +46,7 @@ type Host = { enabled: boolean; ssl_forced: boolean; certificate_id: number; + http2_support: boolean; meta?: { nginx_online?: boolean }; }; @@ -191,6 +192,33 @@ export const ProxiesBlock = ({ servers }: { servers: Server[] }) => { }); }; + /** + * Turn HTTP/2 on for a host that predates it being the default. + * + * Offered rather than done on load, even though it is one field and always the right answer: a + * panel that silently rewrites the proxy while you are reading it is not something to build, and + * the change momentarily reloads nginx for every site behind it. + * + * Only shown for a host that HAS a certificate — HTTP/2 is negotiated during the TLS handshake, so + * on a plain host the setting is stored and never used, and offering it there would be offering a + * button that does nothing visible. + */ + const upgrade = async (host: Host) => { + setBusy(`http2:${host.id}`); + setFailed(false); + setOutput(null); + try { + await clientRef.current.put(`/proxy-manager/npm/nginx/proxy-hosts/${host.id}`, { http2_support: true }); + setOutput(`${host.domain_names.join(', ')} → HTTP/2`); + await load(); + } catch (failure) { + setOutput(readableError(failure)); + setFailed(true); + } finally { + setBusy(null); + } + }; + const secure = async (host: Host) => { const names = host.domain_names; setBusy(`cert:${host.id}`); @@ -320,6 +348,21 @@ export const ProxiesBlock = ({ servers }: { servers: Server[] }) => { )}

+ {/* + Only when it is both possible and missing. A host created since http2_support became the + default never shows this, which is the point — it is a repair, not a setting. + */} + {host.certificate_id > 0 && !host.http2_support && ( + + )} + {!host.certificate_id && (