From f89c2ed06045132cf7ef9243ae7de6a2cb4ef78c Mon Sep 17 00:00:00 2001 From: Chris Sherwood Date: Thu, 4 Jun 2026 12:35:15 -0700 Subject: [PATCH] feat(supply-depot): scheme-aware service links (https:port) for TLS-serving apps --- admin/app/controllers/system_controller.ts | 7 ++++++- admin/app/services/docker_service.ts | 6 ++++++ admin/inertia/lib/navigation.ts | 7 +++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/admin/app/controllers/system_controller.ts b/admin/app/controllers/system_controller.ts index f364291..1fc5a0d 100644 --- a/admin/app/controllers/system_controller.ts +++ b/admin/app/controllers/system_controller.ts @@ -499,6 +499,9 @@ export default class SystemController { // Merge the form fields into the app's existing config rather than rebuilding from scratch, // so advanced settings a curated app ships with (GPU device requests, special env, etc.) are // preserved across an edit. + // Preserve an explicit scheme (e.g. ui_location "https:8480") across an edit — otherwise a + // TLS-serving app's Open link would silently revert to http after any reconfigure. + const prevScheme = (service.ui_location || '').match(/^(https?):\d+$/)?.[1] const { containerConfig, uiLocation } = this.mergeCustomContainerConfig( service.container_config, payload @@ -506,7 +509,9 @@ export default class SystemController { service.friendly_name = payload.friendly_name service.container_image = payload.image service.container_config = JSON.stringify(containerConfig) - service.ui_location = uiLocation + service.ui_location = prevScheme && uiLocation && /^\d+$/.test(uiLocation) + ? `${prevScheme}:${uiLocation}` + : uiLocation service.category = payload.category ?? service.category ?? 'custom' if (payload.icon) service.icon = payload.icon // Flag as user-modified so the seeder stops overwriting this app's config on future runs. diff --git a/admin/app/services/docker_service.ts b/admin/app/services/docker_service.ts index 19b27e0..71e208e 100644 --- a/admin/app/services/docker_service.ts +++ b/admin/app/services/docker_service.ts @@ -198,6 +198,12 @@ export class DockerService { const hostname = process.env.NODE_ENV === 'production' ? serviceName : 'localhost' + // "https:8480" / "http:8480" — explicit scheme + port (e.g. an app serving its own TLS). + const schemePort = service.ui_location?.match(/^(https?):(\d+)$/) + if (schemePort) { + return `${schemePort[1]}://${hostname}:${schemePort[2]}` + } + // First, check if ui_location is set and is a valid port number if (service.ui_location && parseInt(service.ui_location, 10)) { return `http://${hostname}:${service.ui_location}` diff --git a/admin/inertia/lib/navigation.ts b/admin/inertia/lib/navigation.ts index 49040ef..b88255e 100644 --- a/admin/inertia/lib/navigation.ts +++ b/admin/inertia/lib/navigation.ts @@ -1,6 +1,13 @@ export function getServiceLink(ui_location: string): string { + // "https:8480" / "http:8480" — an explicit scheme + port served on the current host. Checked + // before the URL parse below because new URL("https:8480") would mis-parse 8480 as the host. + const schemePort = ui_location.match(/^(https?):(\d+)$/); + if (schemePort) { + return `${schemePort[1]}://${window.location.hostname}:${schemePort[2]}`; + } + // Check if the ui location is a valid URL try { const url = new URL(ui_location);