// Runtime configuration, read once from the environment at startup. // Defaults are chosen to be secure-but-non-breaking; tighten them in production // (see README for the full list and the "run behind TLS" note). const env = process.env /** parseInt with a default that distinguishes "unset" from "explicit 0". */ function intEnv(value: string | undefined, defaultValue: number): number { if (value === undefined || value === "") return defaultValue; const parsed = parseInt(value, 10); return Number.isFinite(parsed) ? parsed : defaultValue; } /** Truthy only for "true"/"1"; anything else (incl. "false", "0", unset) is off. */ function boolEnv(value: string | undefined): boolean { return value === "true" || value === "1"; } export const config = { // Hard cap on a single upload, in bytes (default 100 MiB). maxUploadBytes: intEnv(Bun.env.MAX_UPLOAD_BYTES, 100 * 1024 * 1024), // Maximum retention in minutes. null = unlimited; when set, every upload's // deletion time is clamped to at most now + maxAgeMinutes. maxAgeMinutes: Bun.env.MAX_AGE_MINUTES ? intEnv(Bun.env.MAX_AGE_MINUTES, 0) || null : null, // Minimum seconds between uploads from the same client IP. 0 = disabled. uploadCooldownSeconds: intEnv(Bun.env.UPLOAD_COOLDOWN_SECONDS, 0), // Set when running behind a trusted TLS-terminating reverse proxy (the usual // production setup). Enables reading X-Forwarded-For / X-Real-IP for the // client IP and adds the Secure flag to the password cookie. Leave off for // direct/local HTTP, otherwise clients can spoof the cooldown key and the // Secure cookie won't be sent over plain HTTP. behindProxy: boolEnv(env.BEHIND_PROXY), };