Use domain-based URLs for services instead of IP:port
- config.ts: Server uses localhost, client uses domain names (coolify.nuc.lan, etc.) - Added serviceDomains mapping and getServiceUrl() helper - services.ts: Updated getCoolifyUrl/getDozzleUrl to use domains - fallbackServices now uses domain-based URLs where available Works from anywhere via Tailscale (no subnet conflicts) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,22 +1,66 @@
|
|||||||
// Server-side configuration (only available in API routes / server components)
|
// Server-side configuration (only available in API routes / server components)
|
||||||
|
// Note: Server runs on NUC, so it can use localhost or container names for internal access
|
||||||
export const serverConfig = {
|
export const serverConfig = {
|
||||||
coolifyToken: process.env.COOLIFY_API_TOKEN || '',
|
coolifyToken: process.env.COOLIFY_API_TOKEN || '',
|
||||||
coolifyApiUrl: process.env.COOLIFY_API_URL || 'http://192.168.1.3:8000/api/v1',
|
coolifyApiUrl: process.env.COOLIFY_API_URL || 'http://localhost:8000/api/v1',
|
||||||
coolifyServerUuid: process.env.COOLIFY_SERVER_UUID || 'qk84w0goo4w48g4ggsoo0oss',
|
coolifyServerUuid: process.env.COOLIFY_SERVER_UUID || 'qk84w0goo4w48g4ggsoo0oss',
|
||||||
coolifyDbUrl: process.env.COOLIFY_DB_URL || '',
|
coolifyDbUrl: process.env.COOLIFY_DB_URL || '',
|
||||||
prometheusUrl: process.env.PROMETHEUS_URL || 'http://192.168.1.3:9091',
|
prometheusUrl: process.env.PROMETHEUS_URL || 'http://localhost:9091',
|
||||||
nodeExporterInstance: process.env.NODE_EXPORTER_INSTANCE || '192.168.1.3:9100',
|
nodeExporterInstance: process.env.NODE_EXPORTER_INSTANCE || 'localhost:9100',
|
||||||
nicDevice: process.env.NIC_DEVICE || 'eno1',
|
nicDevice: process.env.NIC_DEVICE || 'eno1',
|
||||||
nucHost: process.env.NUC_HOST || '192.168.1.3',
|
nucHost: process.env.NUC_HOST || 'localhost',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Client-side configuration (available everywhere via NEXT_PUBLIC_ prefix)
|
// Client-side configuration (available everywhere via NEXT_PUBLIC_ prefix)
|
||||||
|
// Uses domain names for browser access (works via Tailscale from anywhere)
|
||||||
export const clientConfig = {
|
export const clientConfig = {
|
||||||
nucHost: process.env.NEXT_PUBLIC_NUC_HOST || '192.168.1.3',
|
// Primary domain-based URLs (preferred - work from anywhere)
|
||||||
coolifyUrl: process.env.NEXT_PUBLIC_COOLIFY_URL || 'http://192.168.1.3:8000',
|
coolifyUrl: process.env.NEXT_PUBLIC_COOLIFY_URL || 'http://coolify.nuc.lan',
|
||||||
|
grafanaUrl: process.env.NEXT_PUBLIC_GRAFANA_URL || 'http://grafana.nuc.lan',
|
||||||
|
dozzleUrl: process.env.NEXT_PUBLIC_DOZZLE_URL || 'http://dozzle.nuc.lan',
|
||||||
|
|
||||||
|
// Fallback host for services without domain routes
|
||||||
|
nucHost: process.env.NEXT_PUBLIC_NUC_HOST || '100.113.153.45',
|
||||||
|
|
||||||
|
// Coolify project identifiers
|
||||||
coolifyProjectUuid: process.env.NEXT_PUBLIC_COOLIFY_PROJECT_UUID || 'a8484ggc88c40w4g4k004ow0',
|
coolifyProjectUuid: process.env.NEXT_PUBLIC_COOLIFY_PROJECT_UUID || 'a8484ggc88c40w4g4k004ow0',
|
||||||
coolifyEnvUuid: process.env.NEXT_PUBLIC_COOLIFY_ENV_UUID || 'dckc0w4ko8s888c4gk84skoo',
|
coolifyEnvUuid: process.env.NEXT_PUBLIC_COOLIFY_ENV_UUID || 'dckc0w4ko8s888c4gk84skoo',
|
||||||
grafanaUrl: process.env.NEXT_PUBLIC_GRAFANA_URL || 'http://192.168.1.3:3333',
|
|
||||||
dozzleUrl: process.env.NEXT_PUBLIC_DOZZLE_URL || 'http://192.168.1.3:9999',
|
|
||||||
dozzleHostId: process.env.NEXT_PUBLIC_DOZZLE_HOST_ID || '6c1738d9-6f12-4ed7-9293-70a91f407347',
|
dozzleHostId: process.env.NEXT_PUBLIC_DOZZLE_HOST_ID || '6c1738d9-6f12-4ed7-9293-70a91f407347',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Domain mappings for services (used for generating URLs)
|
||||||
|
export const serviceDomains: Record<string, string> = {
|
||||||
|
coolify: 'http://coolify.nuc.lan',
|
||||||
|
gitea: 'http://gitea.nuc.lan',
|
||||||
|
outline: 'http://outline.nuc.lan',
|
||||||
|
files: 'http://files.nuc.lan',
|
||||||
|
filebrowser: 'http://files.nuc.lan',
|
||||||
|
mail: 'http://mail.nuc.lan',
|
||||||
|
snappymail: 'http://mail.nuc.lan',
|
||||||
|
vault: 'http://vault.nuc.lan',
|
||||||
|
vaultwarden: 'http://vault.nuc.lan',
|
||||||
|
homepage: 'http://homepage.nuc.lan',
|
||||||
|
grafana: 'http://grafana.nuc.lan',
|
||||||
|
dozzle: 'http://dozzle.nuc.lan',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the URL for a service, preferring domain-based URL if available
|
||||||
|
*/
|
||||||
|
export function getServiceUrl(serviceName: string, port?: number): string {
|
||||||
|
const lower = serviceName.toLowerCase();
|
||||||
|
|
||||||
|
// Check for domain mapping first
|
||||||
|
for (const [key, url] of Object.entries(serviceDomains)) {
|
||||||
|
if (lower.includes(key)) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to port-based URL
|
||||||
|
if (port) {
|
||||||
|
return `http://${clientConfig.nucHost}:${port}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `http://${clientConfig.nucHost}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ export interface DiscoveredService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getCoolifyUrl(service: DiscoveredService): string {
|
export function getCoolifyUrl(service: DiscoveredService): string {
|
||||||
const base = process.env.NEXT_PUBLIC_COOLIFY_URL || 'http://192.168.1.3:8000';
|
const base = process.env.NEXT_PUBLIC_COOLIFY_URL || 'http://coolify.nuc.lan';
|
||||||
const project = process.env.NEXT_PUBLIC_COOLIFY_PROJECT_UUID || 'a8484ggc88c40w4g4k004ow0';
|
const project = process.env.NEXT_PUBLIC_COOLIFY_PROJECT_UUID || 'a8484ggc88c40w4g4k004ow0';
|
||||||
const env = process.env.NEXT_PUBLIC_COOLIFY_ENV_UUID || 'dckc0w4ko8s888c4gk84skoo';
|
const env = process.env.NEXT_PUBLIC_COOLIFY_ENV_UUID || 'dckc0w4ko8s888c4gk84skoo';
|
||||||
return `${base}/project/${project}/environment/${env}/${service.resourceType}/${service.uuid}`;
|
return `${base}/project/${project}/environment/${env}/${service.resourceType}/${service.uuid}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDozzleUrl(service?: DiscoveredService): string {
|
export function getDozzleUrl(service?: DiscoveredService): string {
|
||||||
const base = process.env.NEXT_PUBLIC_DOZZLE_URL || 'http://192.168.1.3:9999';
|
const base = process.env.NEXT_PUBLIC_DOZZLE_URL || 'http://dozzle.nuc.lan';
|
||||||
const hostId = process.env.NEXT_PUBLIC_DOZZLE_HOST_ID || '6c1738d9-6f12-4ed7-9293-70a91f407347';
|
const hostId = process.env.NEXT_PUBLIC_DOZZLE_HOST_ID || '6c1738d9-6f12-4ed7-9293-70a91f407347';
|
||||||
if (service?.container) {
|
if (service?.container) {
|
||||||
return `${base}/container/${hostId}~${service.container}`;
|
return `${base}/container/${hostId}~${service.container}`;
|
||||||
@@ -43,30 +43,30 @@ export interface Bookmark {
|
|||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { clientConfig } from './config';
|
import { clientConfig, getServiceUrl } from './config';
|
||||||
|
|
||||||
const h = clientConfig.nucHost;
|
const h = clientConfig.nucHost;
|
||||||
|
|
||||||
export const fallbackServices: Service[] = [
|
export const fallbackServices: Service[] = [
|
||||||
// Infrastructure
|
// Infrastructure - prefer domain-based URLs
|
||||||
{ name: 'Coolify', url: `http://${h}:8000`, port: 8000, icon: 'server', category: 'infrastructure', description: 'Container deployment & management' },
|
{ name: 'Coolify', url: 'http://coolify.nuc.lan', port: 8000, icon: 'server', category: 'infrastructure', description: 'Container deployment & management' },
|
||||||
{ name: 'Dozzle', url: `http://${h}:9999`, port: 9999, icon: 'scroll-text', category: 'infrastructure', description: 'Real-time Docker log viewer' },
|
{ name: 'Dozzle', url: 'http://dozzle.nuc.lan', port: 9999, icon: 'scroll-text', category: 'infrastructure', description: 'Real-time Docker log viewer' },
|
||||||
{ name: 'Playwriter Browser', url: `http://${h}:6081/vnc.html`, port: 6081, icon: 'monitor', category: 'infrastructure', description: 'Remote browser for automation' },
|
{ name: 'Playwriter Browser', url: `http://${h}:6081/vnc.html`, port: 6081, icon: 'monitor', category: 'infrastructure', description: 'Remote browser for automation' },
|
||||||
|
|
||||||
// Automation
|
// Automation
|
||||||
{ name: 'n8n', url: `http://${h}:5678`, port: 5678, icon: 'workflow', category: 'automation', description: 'Workflow automation platform' },
|
{ name: 'n8n', url: `http://${h}:5678`, port: 5678, icon: 'workflow', category: 'automation', description: 'Workflow automation platform' },
|
||||||
|
|
||||||
// Development
|
// Development - prefer domain-based URLs
|
||||||
{ name: 'Gitea', url: `http://${h}:3030`, port: 3030, icon: 'git-branch', category: 'development', description: 'Self-hosted Git service' },
|
{ name: 'Gitea', url: 'http://gitea.nuc.lan', port: 3030, icon: 'git-branch', category: 'development', description: 'Self-hosted Git service' },
|
||||||
{ name: 'CloudBeaver', url: `http://${h}:8978`, port: 8978, icon: 'database', category: 'development', description: 'Database management UI' },
|
{ name: 'CloudBeaver', url: `http://${h}:8978`, port: 8978, icon: 'database', category: 'development', description: 'Database management UI' },
|
||||||
{ name: 'Adminer', url: `http://${h}:8088`, port: 8088, icon: 'table', category: 'development', description: 'Lightweight database admin' },
|
{ name: 'Adminer', url: `http://${h}:8088`, port: 8088, icon: 'table', category: 'development', description: 'Lightweight database admin' },
|
||||||
|
|
||||||
// Knowledge
|
// Knowledge - prefer domain-based URLs
|
||||||
{ name: 'Outline', url: `http://${h}:3080`, port: 3080, icon: 'book-open', category: 'knowledge', description: 'Team wiki & documentation' },
|
{ name: 'Outline', url: 'http://outline.nuc.lan', port: 3080, icon: 'book-open', category: 'knowledge', description: 'Team wiki & documentation' },
|
||||||
{ name: 'NocoDB', url: `http://${h}:8084`, port: 8084, icon: 'grid-3x3', category: 'knowledge', description: 'Airtable alternative database' },
|
{ name: 'NocoDB', url: `http://${h}:8084`, port: 8084, icon: 'grid-3x3', category: 'knowledge', description: 'Airtable alternative database' },
|
||||||
|
|
||||||
// Storage
|
// Storage - prefer domain-based URLs
|
||||||
{ name: 'FileBrowser', url: `http://${h}:8085`, port: 8085, icon: 'folder', category: 'storage', description: 'Web file manager' },
|
{ name: 'FileBrowser', url: 'http://files.nuc.lan', port: 8085, icon: 'folder', category: 'storage', description: 'Web file manager' },
|
||||||
{ name: 'MinIO', url: `http://${h}:9001`, port: 9001, icon: 'hard-drive', category: 'storage', description: 'S3-compatible object storage' },
|
{ name: 'MinIO', url: `http://${h}:9001`, port: 9001, icon: 'hard-drive', category: 'storage', description: 'S3-compatible object storage' },
|
||||||
{ name: 'Kopia', url: `http://${h}:51515`, port: 51515, icon: 'archive', category: 'storage', description: 'Backup & restore' },
|
{ name: 'Kopia', url: `http://${h}:51515`, port: 51515, icon: 'archive', category: 'storage', description: 'Backup & restore' },
|
||||||
|
|
||||||
@@ -74,8 +74,8 @@ export const fallbackServices: Service[] = [
|
|||||||
{ name: 'Uptime Kuma', url: `http://${h}:3001`, port: 3001, icon: 'activity', category: 'monitoring', description: 'Service status monitoring' },
|
{ name: 'Uptime Kuma', url: `http://${h}:3001`, port: 3001, icon: 'activity', category: 'monitoring', description: 'Service status monitoring' },
|
||||||
{ name: 'Ntfy', url: `http://${h}:8333`, port: 8333, icon: 'bell', category: 'monitoring', description: 'Push notifications server' },
|
{ name: 'Ntfy', url: `http://${h}:8333`, port: 8333, icon: 'bell', category: 'monitoring', description: 'Push notifications server' },
|
||||||
|
|
||||||
// Security
|
// Security - prefer domain-based URLs
|
||||||
{ name: 'Vaultwarden', url: `http://${h}:8222`, port: 8222, icon: 'lock', category: 'security', description: 'Password manager' },
|
{ name: 'Vaultwarden', url: 'http://vault.nuc.lan', port: 8222, icon: 'lock', category: 'security', description: 'Password manager' },
|
||||||
{ name: 'Authentik', url: `http://${h}:9090`, port: 9090, icon: 'shield', category: 'security', description: 'Identity provider & SSO' },
|
{ name: 'Authentik', url: `http://${h}:9090`, port: 9090, icon: 'shield', category: 'security', description: 'Identity provider & SSO' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user