diff --git a/apps/server/src/providers/filesystem-storage.provider.ts b/apps/server/src/providers/filesystem-storage.provider.ts index 72ebce8..c16024b 100644 --- a/apps/server/src/providers/filesystem-storage.provider.ts +++ b/apps/server/src/providers/filesystem-storage.provider.ts @@ -1,5 +1,6 @@ import { env } from "../env"; import { StorageProvider } from "../types/storage"; +import { IS_RUNNING_IN_CONTAINER } from "../utils/container-detection"; import * as crypto from "crypto"; import * as fsSync from "fs"; import * as fs from "fs/promises"; @@ -15,25 +16,12 @@ export class FilesystemStorageProvider implements StorageProvider { private downloadTokens = new Map(); private constructor() { - this.uploadsDir = this.isDocker() ? "/app/server/uploads" : path.join(process.cwd(), "uploads"); + this.uploadsDir = IS_RUNNING_IN_CONTAINER ? "/app/server/uploads" : path.join(process.cwd(), "uploads"); this.ensureUploadsDir(); setInterval(() => this.cleanExpiredTokens(), 5 * 60 * 1000); } - private isDocker(): boolean { - try { - fsSync.statSync("/.dockerenv"); - return true; - } catch { - try { - return fsSync.readFileSync("/proc/self/cgroup", "utf8").includes("docker"); - } catch { - return false; - } - } - } - public static getInstance(): FilesystemStorageProvider { if (!FilesystemStorageProvider.instance) { FilesystemStorageProvider.instance = new FilesystemStorageProvider(); @@ -229,8 +217,10 @@ export class FilesystemStorageProvider implements StorageProvider { if (encryptedBuffer.length > 16) { try { return this.decryptFileBuffer(encryptedBuffer); - } catch (error) { - console.warn("Failed to decrypt with new method, trying legacy format"); + } catch (error: unknown) { + if (error instanceof Error) { + console.warn("Failed to decrypt with new method, trying legacy format", error.message); + } return this.decryptFileLegacy(encryptedBuffer); } } diff --git a/apps/server/src/server.ts b/apps/server/src/server.ts index ecc6084..e8d1b7c 100644 --- a/apps/server/src/server.ts +++ b/apps/server/src/server.ts @@ -11,9 +11,9 @@ import { reverseShareRoutes } from "./modules/reverse-share/routes"; import { shareRoutes } from "./modules/share/routes"; import { storageRoutes } from "./modules/storage/routes"; import { userRoutes } from "./modules/user/routes"; +import { IS_RUNNING_IN_CONTAINER } from "./utils/container-detection"; import fastifyMultipart from "@fastify/multipart"; import fastifyStatic from "@fastify/static"; -import * as fsSync from "fs"; import * as fs from "fs/promises"; import crypto from "node:crypto"; import path from "path"; @@ -27,21 +27,7 @@ if (typeof global.crypto === "undefined") { } async function ensureDirectories() { - // Use /app/server paths in Docker, current directory for local development - const isDocker = (() => { - try { - fsSync.statSync("/.dockerenv"); - return true; - } catch { - try { - return fsSync.readFileSync("/proc/self/cgroup", "utf8").includes("docker"); - } catch { - return false; - } - } - })(); - - const baseDir = isDocker ? "/app/server" : process.cwd(); + const baseDir = IS_RUNNING_IN_CONTAINER ? "/app/server" : process.cwd(); const uploadsDir = path.join(baseDir, "uploads"); const tempChunksDir = path.join(baseDir, "temp-chunks"); @@ -78,20 +64,7 @@ async function startServer() { }); if (env.ENABLE_S3 !== "true") { - const isDocker = (() => { - try { - fsSync.statSync("/.dockerenv"); - return true; - } catch { - try { - return fsSync.readFileSync("/proc/self/cgroup", "utf8").includes("docker"); - } catch { - return false; - } - } - })(); - - const baseDir = isDocker ? "/app/server" : process.cwd(); + const baseDir = IS_RUNNING_IN_CONTAINER ? "/app/server" : process.cwd(); const uploadsPath = path.join(baseDir, "uploads"); await app.register(fastifyStatic, { diff --git a/apps/server/src/utils/container-detection.ts b/apps/server/src/utils/container-detection.ts new file mode 100644 index 0000000..a079422 --- /dev/null +++ b/apps/server/src/utils/container-detection.ts @@ -0,0 +1,45 @@ +import * as fsSync from "fs"; + +/** + * Determines if the application is running inside a container environment. + * Checks common container indicators like /.dockerenv and cgroup file patterns. + * + * This function caches its result after the first call for performance. + * + * @returns {boolean} True if running in a container, false otherwise. + */ +function isRunningInContainer(): boolean { + try { + if (fsSync.existsSync("/.dockerenv")) { + return true; + } + + const cgroupContent = fsSync.readFileSync("/proc/self/cgroup", "utf8"); + const containerPatterns = [ + "docker", + "containerd", + "lxc", + "kubepods", + "pod", + "/containers/", + "system.slice/container-", + ]; + + for (const pattern of containerPatterns) { + if (cgroupContent.includes(pattern)) { + return true; + } + } + + if (fsSync.existsSync("/.well-known/container")) { + return true; + } + } catch (e: unknown) { + if (e instanceof Error) { + console.warn("Could not perform full container detection:", e.message); + } + } + return false; +} + +export const IS_RUNNING_IN_CONTAINER = isRunningInContainer();