import dotenv from "dotenv"; import { promises as fs } from "fs"; import { readFileSync } from "fs"; import path from "path"; import { fileURLToPath } from "url"; import { AutoSSLSetup } from "./utils/auto-ssl-setup.js"; import { AuthManager } from "./utils/auth-manager.js"; import { DataCrypto } from "./utils/data-crypto.js"; import { SystemCrypto } from "./utils/system-crypto.js"; import { systemLogger, versionLogger } from "./utils/logger.js"; (async () => { try { dotenv.config({ quiet: true }); const dataDir = process.env.DATA_DIR || "./db/data"; const envPath = path.join(dataDir, ".env"); try { await fs.access(envPath); const persistentConfig = dotenv.config({ path: envPath, quiet: true }); if (persistentConfig.parsed) { Object.assign(process.env, persistentConfig.parsed); } } catch (error) {} let version = "unknown"; const versionSources = [ () => process.env.VERSION, () => { try { const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse( readFileSync(packageJsonPath, "utf-8"), ); return packageJson.version; } catch { return null; } }, () => { try { const __filename = fileURLToPath(import.meta.url); const packageJsonPath = path.join( path.dirname(__filename), "../../../package.json", ); const packageJson = JSON.parse( readFileSync(packageJsonPath, "utf-8"), ); return packageJson.version; } catch { return null; } }, () => { try { const packageJsonPath = path.join("/app", "package.json"); const packageJson = JSON.parse( readFileSync(packageJsonPath, "utf-8"), ); return packageJson.version; } catch { return null; } }, ]; for (const getVersion of versionSources) { try { const foundVersion = getVersion(); if (foundVersion && foundVersion !== "unknown") { version = foundVersion; break; } } catch { continue; } } versionLogger.info(`Termix Backend starting - Version: ${version}`, { operation: "startup", version: version, }); const systemCrypto = SystemCrypto.getInstance(); await systemCrypto.initializeJWTSecret(); await systemCrypto.initializeDatabaseKey(); await systemCrypto.initializeInternalAuthToken(); await AutoSSLSetup.initialize(); const dbModule = await import("./database/db/index.js"); await dbModule.initializeDatabase(); const authManager = AuthManager.getInstance(); await authManager.initialize(); DataCrypto.initialize(); await import("./database/database.js"); await import("./ssh/terminal.js"); await import("./ssh/tunnel.js"); await import("./ssh/file-manager.js"); await import("./ssh/server-stats.js"); await import("./ssh/docker.js"); await import("./ssh/docker-console.js"); await import("./dashboard.js"); process.on("SIGINT", () => { systemLogger.info( "Received SIGINT signal, initiating graceful shutdown...", { operation: "shutdown" }, ); process.exit(0); }); process.on("SIGTERM", () => { systemLogger.info( "Received SIGTERM signal, initiating graceful shutdown...", { operation: "shutdown" }, ); process.exit(0); }); process.on("uncaughtException", (error) => { systemLogger.error("Uncaught exception occurred", error, { operation: "error_handling", }); process.exit(1); }); process.on("unhandledRejection", (reason) => { systemLogger.error("Unhandled promise rejection", reason, { operation: "error_handling", }); process.exit(1); }); } catch (error) { systemLogger.error("Failed to initialize backend services", error, { operation: "startup_failed", }); process.exit(1); } })();