Enhance service card creation with Tailscale IP support and update services.xml to include tailscale-ip configuration

This commit is contained in:
MayaChat
2025-11-24 12:01:00 -05:00
parent 3b09920eee
commit 242d046d1f
2 changed files with 25 additions and 8 deletions

View File

@@ -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',

View File

@@ -2,6 +2,9 @@
<!--
services.xml - simple list of services for the homepage
Configuration:
- tailscale-ip: IP address to use for local services (optional, default: auto-detect)
Structure:
- Use <group> elements to organize services into categories
- Each group has a 'name' attribute for the category title
@@ -25,7 +28,7 @@
* Red dot if offline/unreachable
- Set check-health="false" to disable automatic checking
-->
<services>
<services tailscale-ip="100.124.17.41">
<group name="Management">
<service id="portainer" name="Portainer" proto="https" port="9443" logo="portainer.svg" />
<service id="uptime-kuma" name="Uptime Kuma" proto="http" port="3001" logo="uptime-kuma.svg" />