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