diff --git a/js/services-loader.js b/js/services-loader.js index 2009309..cf0c5f4 100644 --- a/js/services-loader.js +++ b/js/services-loader.js @@ -18,6 +18,11 @@ throw new Error('XML parsing error: ' + parseError.textContent); } + // Get Tailscale IP from root services element + const servicesRoot = doc.getElementsByTagName('services')[0]; + const tailscaleIP = servicesRoot ? servicesRoot.getAttribute('tailscale-ip') : null; + console.log('Tailscale IP:', tailscaleIP || 'not configured'); + // Check if we have groups or just services const groups = Array.from(doc.getElementsByTagName('group')); const hasGroups = groups.length > 0; @@ -47,7 +52,7 @@ grid.className = 'grid'; services.forEach(s => { - const card = createServiceCard(s, host, allServices); + const card = createServiceCard(s, host, allServices, tailscaleIP); grid.appendChild(card); }); @@ -67,7 +72,7 @@ grid.id = 'services-grid'; services.forEach(s => { - const card = createServiceCard(s, host, allServices); + const card = createServiceCard(s, host, allServices, tailscaleIP); grid.appendChild(card); }); @@ -75,7 +80,7 @@ } // Function to create a service card - function createServiceCard(s, host, allServices) { + function createServiceCard(s, host, allServices, tailscaleIP) { const name = s.getAttribute('name') || s.getAttribute('id') || 'unknown'; const proto = s.getAttribute('proto') || 'http'; const port = s.getAttribute('port') || ''; @@ -86,21 +91,30 @@ // Build href: prefer explicit host attribute when present. let href = ''; + let healthCheckUrl = ''; // Separate URL for health checks + if(hostAttr){ + // Service has a public hostname or URL if(/^https?:\/\//i.test(hostAttr)){ href = hostAttr; + healthCheckUrl = hostAttr; } else { const hasPortInHost = /:\d+$/.test(hostAttr); if(hasPortInHost){ href = `${proto}://${hostAttr}`; + healthCheckUrl = `${proto}://${hostAttr}`; } else { href = `https://${hostAttr}`; + healthCheckUrl = `https://${hostAttr}`; } } } else { + // Local service - use Tailscale IP if configured, otherwise current hostname + const targetHost = tailscaleIP || host; let portPart = ''; if(port && !((proto==='http'&&port==='80')||(proto==='https'&&port==='443'))){ portPart = ':'+port; } - href = `${proto}://${host}${portPart}`; + href = `${proto}://${targetHost}${portPart}`; + healthCheckUrl = `${proto}://${targetHost}${portPart}`; } const a = document.createElement('a'); @@ -134,17 +148,17 @@ statusDot.title = 'Status: maintenance'; currentStatus = 'maintenance'; a.appendChild(statusDot); - } else if(checkHealth && href){ + } else if(checkHealth && healthCheckUrl){ // Show checking indicator initially a.appendChild(statusDot); - // Perform health check + // Perform health check using healthCheckUrl (Tailscale IP for local services) (async function performHealthCheck(){ try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout - const response = await fetch(href, { + const response = await fetch(healthCheckUrl, { method: 'HEAD', mode: 'no-cors', // Allow cross-origin requests cache: 'no-cache', diff --git a/services.xml b/services.xml index 6077512..c63658e 100644 --- a/services.xml +++ b/services.xml @@ -2,6 +2,9 @@ - +