This commit is contained in:
Mateusz Gruszczyński committed 2026-10-11 13:56:30 +02:00
1 parent 95c55da2ee
commit d942c1a35d
42 files changed
+1265 -109

No files matched your search

+11 -3
View File
@@ -2734,9 +2734,17 @@
data-i18n="administrationHttps">Enable HTTPS for administration</span></label>
<label><span data-i18n="administrationCertificate">Certificate</span><select
id="admin-certificate"></select></label>
<label><span data-i18n="administrationHosts">Allowed DNS hostnames</span><textarea
id="admin-hosts" rows="4" spellcheck="false"
placeholder="admin.example.com"></textarea></label>
<label><span data-i18n="administrationPublicOrigin">Public panel HTTPS origin (optional)</span><input
id="admin-public-origin" maxlength="255" placeholder="https://panel.example.com"
type="url" spellcheck="false" autocomplete="off" /></label>
<p class="fine" data-i18n="administrationPublicOriginHelp">When behind a trusted reverse proxy, enter the panel's external HTTPS address once. Its DNS name is automatically allowed. A restart is required.</p>
<details id="admin-extra-hosts-details">
<summary data-i18n="administrationHostsAdvanced">Advanced: additional allowed DNS hostnames</summary>
<label><span data-i18n="administrationHosts">Additional allowed DNS hostnames</span><textarea
id="admin-hosts" rows="4" spellcheck="false"
placeholder="other-admin.example.com"></textarea></label>
<p class="fine" data-i18n="administrationHostsHelp">Only extra hostnames belong here. The hostname from the public panel URL is automatically included; without a public URL this remains an independent strict allowlist.</p>
</details>
<label><span data-i18n="administrationSessionDays">Administrator session lifetime
(days)</span><input id="admin-session-days" min="7" max="30" step="1"
type="number" required="" /></label>
+18 -2
View File
@@ -8,6 +8,19 @@
? "logging"
: (typeof location !== "undefined" && location.pathname === "/settings" ? new URLSearchParams(location.search).get("tab") : null);
const tabAliases = { http2: "connections" };
// Keep the public panel hostname implicit. Legacy configurations may have
// written it into allowed_hosts in 0.31.4; do not show/save it twice.
function pinnedAdminHostname(value) {
try {
const url = new URL(value);
return url.protocol === "https:" ? url.hostname.toLowerCase().replace(/\.$/, "") : "";
} catch { return ""; }
}
function additionalAdminHosts(hosts, origin) {
const pinned = pinnedAdminHostname(origin);
return hosts.map(host => host.trim()).filter(host =>
host && (!pinned || host.replace(/\.$/, "").toLowerCase() !== pinned));
}
const normalizedRequestedTab = tabAliases[requestedTab] || requestedTab;
let active = buttons.some(button => button.dataset.settingsTab === normalizedRequestedTab) ? normalizedRequestedTab : defaultTab;
function applySettingsSearch() {
@@ -212,7 +225,10 @@ curl --fail --show-error --request POST \
$("admin-tls").checked = !!admin.tls;
const current = admin.certificate_id || "", generated = document.createElement("option"); generated.value = ""; generated.textContent = t("administrationGeneratedCertificate");
$("admin-certificate").replaceChildren(generated, ...(envelope.config.tls?.certificates || []).map(cert => { const o = document.createElement("option"); o.value = cert.id; o.textContent = cert.id; return o; })); $("admin-certificate").value = current;
$("admin-hosts").value = (admin.allowed_hosts || []).join("\n");
const extraHosts = additionalAdminHosts(admin.allowed_hosts || [], admin.public_origin);
$("admin-hosts").value = extraHosts.join("\n");
$("admin-extra-hosts-details").open = extraHosts.length > 0;
$("admin-public-origin").value = admin.public_origin || "";
$("admin-session-days").value = Number(admin.session_days || 30);
for (const codec of ["zstd", "br", "gzip"]) $(`admin-compression-${codec}`).checked = admin.panel_compression?.[codec] !== false;
}
@@ -300,7 +316,7 @@ curl --fail --show-error --request POST \
}, "prometheus");
bindSettingsForm("administration-form", next => {
const locked = !!latestStatus?.administration?.listen_locked;
next.administration = { listen: locked ? null : $("admin-listen").value.trim(), tls: $("admin-tls").checked, certificate_id: $("admin-tls").checked ? ($("admin-certificate").value || null) : null, allowed_hosts: $("admin-hosts").value.split(/[\n,]+/).map(v => v.trim()).filter(Boolean), session_days: Number($("admin-session-days").value), panel_compression: Object.fromEntries(["zstd", "br", "gzip"].map(codec => [codec, $(`admin-compression-${codec}`).checked])) };
next.administration = { listen: locked ? null : $("admin-listen").value.trim(), tls: $("admin-tls").checked, certificate_id: $("admin-tls").checked ? ($("admin-certificate").value || null) : null, allowed_hosts: additionalAdminHosts($("admin-hosts").value.split(/[\n,]+/), $("admin-public-origin").value.trim()), public_origin: $("admin-public-origin").value.trim() || null, session_days: Number($("admin-session-days").value), panel_compression: Object.fromEntries(["zstd", "br", "gzip"].map(codec => [codec, $(`admin-compression-${codec}`).checked])) };
}, "administration");
bindSettingsForm("tls-policy-form", next => {
if (!$("tls-policy-12").checked && !$("tls-policy-13").checked) throw fieldError($("tls-policy-12"), t("tlsPolicyVersionRequired"));