import "./loadEnv.js"; import express from "express"; import session from "express-session"; import FileStoreFactory from "session-file-store"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; import { mkdirSync, existsSync } from "node:fs"; import { env, warnIfAuthNotConfigured } from "./env.js"; import { resolveDataPath } from "./paths.js"; import { runMigrations } from "./db/migrate.js"; import { authRouter } from "./auth/router.js"; import { meRouter } from "./routes/me.js"; import { usersRouter } from "./routes/users.js"; import { auditLogRouter } from "./routes/auditLog.js"; import { diagLogRouter } from "./routes/diagLog.js"; import { secretsRouter } from "./routes/secrets.js"; import { ipamRouter } from "./routes/ipam.js"; import { dnsRouter } from "./routes/dns.js"; import { serversRouter } from "./routes/servers.js"; import { tasksRouter } from "./routes/tasks.js"; import { agentReportRouter } from "./routes/agentReport.js"; import { integrationsRouter } from "./routes/integrations.js"; import { settingsRouter } from "./routes/settings.js"; import { searchRouter } from "./routes/search.js"; import { sessionsRouter } from "./routes/sessions.js"; import { maintenanceRouter } from "./routes/maintenance.js"; import { domainsRouter } from "./routes/domains.js"; import { consistencyRouter } from "./routes/consistency.js"; import { privacyRouter } from "./routes/privacy.js"; import { tagsRouter } from "./routes/tags.js"; import { initSecretExpiryScheduler } from "./services/secretExpiryScheduler.js"; import { initTailscaleKeyExpiryScheduler } from "./services/tailscaleKeyExpiryScheduler.js"; import { initLogRetentionScheduler } from "./services/logRetentionScheduler.js"; import { initDockerUpdateScheduler } from "./services/dockerUpdateScheduler.js"; import { initProxmoxBackupScheduler } from "./services/proxmoxBackupScheduler.js"; import { initQuietHoursScheduler } from "./services/quietHoursScheduler.js"; import { initHealthScheduler } from "./services/healthScheduler.js"; warnIfAuthNotConfigured(); await runMigrations(); await initSecretExpiryScheduler(); await initTailscaleKeyExpiryScheduler(); await initLogRetentionScheduler(); await initDockerUpdateScheduler(); await initProxmoxBackupScheduler(); await initQuietHoursScheduler(); await initHealthScheduler(); const __dirname = dirname(fileURLToPath(import.meta.url)); const webDist = join(__dirname, "..", "..", "web", "dist"); const agentDir = join(__dirname, "..", "..", "agent"); const FileStore = FileStoreFactory(session); const sessionDir = resolveDataPath(env.sessionDir); mkdirSync(sessionDir, { recursive: true }); const app = express(); app.set("trust proxy", 1); app.use(express.json()); app.use( session({ store: new FileStore({ path: sessionDir, logFn: () => {} }), secret: env.sessionSecret, resave: false, saveUninitialized: false, cookie: { httpOnly: true, sameSite: "lax", secure: env.nodeEnv === "production", maxAge: 7 * 24 * 60 * 60 * 1000, }, }), ); app.get("/health", (_req, res) => res.json({ ok: true })); // Publicly readable so `curl .../agent/linux/install.sh | bash` works from a // freshly provisioned server with no prior session. Contains no secrets. if (existsSync(agentDir)) { app.use("/agent", express.static(agentDir)); } app.use("/auth", authRouter); app.use("/api/me", meRouter); app.use("/api/users", usersRouter); app.use("/api/audit-log", auditLogRouter); app.use("/api/diag-log", diagLogRouter); app.use("/api/secrets", secretsRouter); app.use("/api/ipam", ipamRouter); app.use("/api/dns", dnsRouter); app.use("/api/servers", serversRouter); app.use("/api/tasks", tasksRouter); app.use("/api/agent/report", agentReportRouter); app.use("/api/integrations", integrationsRouter); app.use("/api/settings", settingsRouter); app.use("/api/search", searchRouter); app.use("/api/sessions", sessionsRouter); app.use("/api/maintenance", maintenanceRouter); app.use("/api/domains", domainsRouter); app.use("/api/consistency", consistencyRouter); app.use("/api/privacy", privacyRouter); app.use("/api/tags", tagsRouter); if (existsSync(webDist)) { app.use(express.static(webDist)); app.get("*", (_req, res) => res.sendFile(join(webDist, "index.html"))); } app.use((err: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => { console.error(err); res.status(500).json({ error: "internal_error" }); }); app.listen(env.port, () => { console.log(`homelab-manager listening on port ${env.port}`); });