diff --git a/neode-ui/src/views/appSession/appSessionConfig.ts b/neode-ui/src/views/appSession/appSessionConfig.ts index 3b6b0a7a..ba9b8c61 100644 --- a/neode-ui/src/views/appSession/appSessionConfig.ts +++ b/neode-ui/src/views/appSession/appSessionConfig.ts @@ -78,6 +78,11 @@ export const HTTPS_PROXY_PATHS: Record = { 'photoprism': '/app/photoprism/', 'endurain': '/app/endurain/', 'dwn': '/app/dwn/', + 'btcpay-server': '/app/btcpay/', + 'nextcloud': '/app/nextcloud/', + 'penpot': '/app/penpot/', + 'grafana': '/app/grafana/', + 'indeedhub': '/app/indeedhub/', } /** External HTTPS apps -- always loaded directly */ @@ -140,16 +145,15 @@ export function resolveAppUrl(id: string, routeQueryPath?: string): string { } } - // HTTPS: use nginx proxy to avoid mixed content - if (window.location.protocol === 'https:') { - const httpsProxy = HTTPS_PROXY_PATHS[id] - if (httpsProxy) return `${window.location.origin}${httpsProxy}` - } + // Always use nginx proxy paths — direct port access fails over Tailscale/VPN + // and when ports aren't exposed externally + const proxyPathEntry = HTTPS_PROXY_PATHS[id] + if (proxyPathEntry) return `${window.location.origin}${proxyPathEntry}` - // HTTP: direct port access (faster, no proxy overhead) + // Fallback: direct port (only for apps without a proxy path) const port = APP_PORTS[id] if (!port) return '' - let base = `http://${window.location.hostname}:${port}` + let base = `${window.location.protocol}//${window.location.hostname}:${port}` if (routeQueryPath) base += routeQueryPath return base }