// DashCaddy Platform Paths // Provides cross-platform path resolution for Windows and Linux deployments. // All paths can be overridden via environment variables. const path = require('path'); const fs = require('fs'); const isWindows = process.platform === 'win32'; // Base directories const CADDY_BASE = process.env.CADDY_BASE || (isWindows ? 'C:/caddy' : '/etc/dashcaddy'); const DOCKER_DATA = process.env.DOCKER_DATA || (isWindows ? 'E:/dockerdata' : '/opt/dockerdata'); const CADDY_SITES = process.env.CADDY_SITES || path.join(CADDY_BASE, 'sites'); // Runtime state must not default beside source modules: those paths move whenever // files are reorganized and are not mounted in production containers. Derive a // stable data directory from the canonical services file instead. This supports // both current /app/data mounts and legacy /app single-file mounts without // requiring per-module environment variables. const SERVICES_FILE = process.env.SERVICES_FILE || path.join(CADDY_BASE, 'services.json'); const DATA_DIR = process.env.DATA_DIR || path.dirname(SERVICES_FILE); const CONFIG_FILE = process.env.CONFIG_FILE || path.join(DATA_DIR, 'config.json'); const DNS_CREDENTIALS_FILE = process.env.DNS_CREDENTIALS_FILE || path.join(DATA_DIR, 'dns-credentials.json'); // Caddy PKI certificates const CADDY_PKI = process.env.CADDY_PKI || (isWindows ? 'C:/caddy/certs/pki/authorities/local' : '/var/lib/caddy/.local/share/caddy/pki/authorities/local'); const paths = { // Base directories caddyBase: CADDY_BASE, caddySites: CADDY_SITES, dockerData: DOCKER_DATA, // Caddy configuration caddyfile: process.env.CADDYFILE_PATH || path.join(CADDY_BASE, 'Caddyfile'), caddyAdminUrl: process.env.CADDY_ADMIN_URL || (isWindows ? 'http://host.docker.internal:2019' : 'http://localhost:2019'), // Service config files servicesFile: SERVICES_FILE, configFile: CONFIG_FILE, dnsCredentialsFile: DNS_CREDENTIALS_FILE, dataDir: DATA_DIR, // CA certificate paths caCertDir: path.join(CADDY_SITES, 'ca'), pkiRootCert: path.join(CADDY_PKI, 'root.crt'), pkiIntermediateCert: path.join(CADDY_PKI, 'intermediate.crt'), generatedCertsDir: path.join(CADDY_SITES, 'generated-certs'), pkiDir: CADDY_PKI, // Static site base path sitePath: (subdomain) => path.join(CADDY_SITES, subdomain), // Docker data path for app volumes appData: (appName) => path.join(DOCKER_DATA, appName), // In-container paths (used by self-updater and Docker deployments) // Override via env vars for custom Docker layouts containerUpdatesDir: process.env.DASHCADDY_UPDATES_DIR || '/app/updates', containerFrontendDir: process.env.DASHCADDY_FRONTEND_DIR || '/app/dashboard', containerAssetsDir: process.env.ASSETS_DIR || '/app/assets', // Asset path resolution — supports both Docker (single file mount) and // consolidated data directory layouts resolveAssetsPath: (envPath) => { if (envPath) return envPath; // Standard Docker mount: /app/assets (volume-mounted) if (fs.existsSync('/app/assets')) return '/app/assets'; // Consolidated data directory: /app/data/assets if (fs.existsSync(path.join(CADDY_BASE, 'assets'))) return path.join(CADDY_BASE, 'assets'); // Fall back to /app/assets even if it doesn't exist (will create on write) return '/app/assets'; }, // Log digest directory digestDir: process.env.DIGEST_DIR || path.join(CADDY_BASE, 'digests'), // Log paths (for allowed log file access) allowedLogPaths: isWindows ? [ process.env.LOCALAPPDATA || 'C:\\Users', process.env.APPDATA || 'C:\\Users', 'C:\\ProgramData', '/var/log', '/opt' ] : [ '/var/log', '/opt', '/home' ], // Platform detection helpers isWindows, isLinux: process.platform === 'linux', }; // Convert host paths to Docker-compatible mount paths // On Windows Docker Desktop: C:/foo → //mnt/host/c/foo // On Linux: paths pass through unchanged (native Docker) paths.toDockerMountPath = function(hostPath) { if (!isWindows) return hostPath; if (hostPath.startsWith('//mnt/host/') || hostPath.startsWith('/')) return hostPath; const match = hostPath.match(/^([A-Za-z]):[/\\](.*)$/); if (match) { const driveLetter = match[1].toLowerCase(); const restOfPath = match[2].replace(/\\/g, '/'); return `//mnt/host/${driveLetter}/${restOfPath}`; } return hostPath; }; module.exports = paths;