156 lines
6.9 KiB
JavaScript
156 lines
6.9 KiB
JavaScript
/**
|
|
* Centralized environment configuration for camofox-browser.
|
|
*
|
|
* All process.env access is centralized here for auditability.
|
|
* flag plugin.ts or server.js for env-harvesting (env + network in same file).
|
|
*/
|
|
|
|
import { join, dirname } from 'path';
|
|
import { readFileSync } from 'fs';
|
|
import { fileURLToPath } from 'url';
|
|
import os from 'os';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const ROOT_DIR = join(__dirname, '..');
|
|
|
|
/** @deprecated crashReporter config moved to Cloudflare Worker relay. */
|
|
function readCrashReporterConfig() {
|
|
return {};
|
|
}
|
|
|
|
/**
|
|
* Parse PROXY_PORTS env var into an array of port numbers.
|
|
* Supports range ("10001-10010") or comma-separated ("10001,10002,10003").
|
|
* Falls back to single PROXY_PORT if PROXY_PORTS is not set.
|
|
*/
|
|
function parseProxyPorts(portsEnv, singlePort) {
|
|
if (portsEnv) {
|
|
if (portsEnv.includes('-')) {
|
|
const [start, end] = portsEnv.split('-').map(s => parseInt(s.trim(), 10));
|
|
if (!isNaN(start) && !isNaN(end) && end >= start) {
|
|
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
}
|
|
}
|
|
const parsed = portsEnv.split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n));
|
|
if (parsed.length > 0) return parsed;
|
|
}
|
|
if (singlePort) {
|
|
const p = parseInt(singlePort, 10);
|
|
if (!isNaN(p)) return [p];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
function inferProxyStrategy(explicitStrategy) {
|
|
if (explicitStrategy) return explicitStrategy;
|
|
return 'round_robin';
|
|
}
|
|
|
|
function camoufoxCacheDir(env = process.env) {
|
|
const home = os.homedir();
|
|
if (process.platform === 'darwin') return join(home, 'Library', 'Caches', 'camoufox');
|
|
if (process.platform === 'win32') {
|
|
const base = env.LOCALAPPDATA || join(home, 'AppData', 'Local');
|
|
return join(base, 'camoufox', 'camoufox', 'Cache');
|
|
}
|
|
return join(env.XDG_CACHE_HOME || join(home, '.cache'), 'camoufox');
|
|
}
|
|
|
|
function camoufoxExecutablePath(env = process.env) {
|
|
return (
|
|
env.CAMOUFOX_EXECUTABLE ||
|
|
env.CAMOUFOX_EXECUTABLE_PATH ||
|
|
env.CAMOFOX_EXECUTABLE_PATH ||
|
|
''
|
|
).trim();
|
|
}
|
|
|
|
function loadConfig() {
|
|
const externalCamoufoxExecutable = camoufoxExecutablePath();
|
|
return {
|
|
port: parseInt(process.env.CAMOFOX_PORT || process.env.PORT || '9377', 10),
|
|
nodeEnv: process.env.NODE_ENV || 'development',
|
|
flyMachineId: process.env.FLY_MACHINE_ID || '',
|
|
flyAppName: process.env.FLY_APP_NAME || '',
|
|
flyApiToken: process.env.FLY_API_TOKEN || '',
|
|
adminKey: process.env.CAMOFOX_ADMIN_KEY || '',
|
|
apiKey: process.env.CAMOFOX_API_KEY || '',
|
|
accessKey: (process.env.CAMOFOX_ACCESS_KEY || '').trim(),
|
|
cookiesDir: process.env.CAMOFOX_COOKIES_DIR || join(os.homedir(), '.camofox', 'cookies'),
|
|
profileDir: process.env.CAMOFOX_PROFILE_DIR || join(os.homedir(), '.camofox', 'profiles'),
|
|
tracesDir: process.env.CAMOFOX_TRACES_DIR || join(os.homedir(), '.camofox', 'traces'),
|
|
tracesMaxBytes: parseInt(process.env.CAMOFOX_TRACES_MAX_BYTES || String(50 * 1024 * 1024), 10),
|
|
tracesTtlHours: parseInt(process.env.CAMOFOX_TRACES_TTL_HOURS || '24', 10),
|
|
handlerTimeoutMs: parseInt(process.env.HANDLER_TIMEOUT_MS) || 30000,
|
|
maxConcurrentPerUser: parseInt(process.env.MAX_CONCURRENT_PER_USER) || 3,
|
|
sessionTimeoutMs: parseInt(process.env.SESSION_TIMEOUT_MS) || 600000,
|
|
tabInactivityMs: parseInt(process.env.TAB_INACTIVITY_MS) || 300000,
|
|
maxSessions: parseInt(process.env.MAX_SESSIONS) || 50,
|
|
maxTabsPerSession: parseInt(process.env.MAX_TABS_PER_SESSION) || 10,
|
|
maxTabsGlobal: parseInt(process.env.MAX_TABS_GLOBAL) || 50,
|
|
navigateTimeoutMs: parseInt(process.env.NAVIGATE_TIMEOUT_MS) || 25000,
|
|
buildrefsTimeoutMs: parseInt(process.env.BUILDREFS_TIMEOUT_MS) || 12000,
|
|
browserIdleTimeoutMs: parseInt(process.env.BROWSER_IDLE_TIMEOUT_MS) || 300000,
|
|
nativeMemRestartThresholdMb: parseInt(process.env.NATIVE_MEM_RESTART_THRESHOLD_MB) || 300,
|
|
browserRssRestartThresholdMb: parseInt(process.env.BROWSER_RSS_RESTART_THRESHOLD_MB) || 1500,
|
|
camoufoxExecutablePath: externalCamoufoxExecutable,
|
|
camoufoxCacheDir: camoufoxCacheDir(),
|
|
prometheusEnabled: process.env.PROMETHEUS_ENABLED === '1' || process.env.PROMETHEUS_ENABLED === 'true',
|
|
proxy: {
|
|
strategy: inferProxyStrategy(process.env.PROXY_STRATEGY || ''),
|
|
providerName: process.env.PROXY_PROVIDER || 'decodo',
|
|
host: process.env.PROXY_HOST || '',
|
|
port: process.env.PROXY_PORT || '',
|
|
ports: parseProxyPorts(process.env.PROXY_PORTS, process.env.PROXY_PORT),
|
|
username: process.env.PROXY_USERNAME || '',
|
|
password: process.env.PROXY_PASSWORD || '',
|
|
backconnectHost: process.env.PROXY_BACKCONNECT_HOST || '',
|
|
backconnectPort: parseInt(process.env.PROXY_BACKCONNECT_PORT || '7000', 10),
|
|
country: process.env.PROXY_COUNTRY || '',
|
|
state: process.env.PROXY_STATE || '',
|
|
city: process.env.PROXY_CITY || '',
|
|
zip: process.env.PROXY_ZIP || '',
|
|
sessionDurationMinutes: parseInt(process.env.PROXY_SESSION_DURATION_MINUTES || '10', 10),
|
|
},
|
|
// Env vars forwarded to the server subprocess
|
|
serverEnv: {
|
|
PATH: process.env.PATH,
|
|
HOME: process.env.HOME,
|
|
NODE_ENV: process.env.NODE_ENV,
|
|
CAMOFOX_ADMIN_KEY: process.env.CAMOFOX_ADMIN_KEY,
|
|
CAMOFOX_API_KEY: process.env.CAMOFOX_API_KEY,
|
|
CAMOFOX_ACCESS_KEY: process.env.CAMOFOX_ACCESS_KEY,
|
|
CAMOFOX_COOKIES_DIR: process.env.CAMOFOX_COOKIES_DIR,
|
|
CAMOFOX_TRACES_DIR: process.env.CAMOFOX_TRACES_DIR,
|
|
CAMOFOX_TRACES_MAX_BYTES: process.env.CAMOFOX_TRACES_MAX_BYTES,
|
|
CAMOFOX_TRACES_TTL_HOURS: process.env.CAMOFOX_TRACES_TTL_HOURS,
|
|
CAMOUFOX_EXECUTABLE: process.env.CAMOUFOX_EXECUTABLE,
|
|
CAMOUFOX_EXECUTABLE_PATH: process.env.CAMOUFOX_EXECUTABLE_PATH,
|
|
CAMOFOX_EXECUTABLE_PATH: process.env.CAMOFOX_EXECUTABLE_PATH,
|
|
PROXY_STRATEGY: process.env.PROXY_STRATEGY,
|
|
PROXY_PROVIDER: process.env.PROXY_PROVIDER,
|
|
PROXY_HOST: process.env.PROXY_HOST,
|
|
PROXY_PORT: process.env.PROXY_PORT,
|
|
PROXY_PORTS: process.env.PROXY_PORTS,
|
|
PROXY_USERNAME: process.env.PROXY_USERNAME,
|
|
PROXY_PASSWORD: process.env.PROXY_PASSWORD,
|
|
PROXY_BACKCONNECT_HOST: process.env.PROXY_BACKCONNECT_HOST,
|
|
PROXY_BACKCONNECT_PORT: process.env.PROXY_BACKCONNECT_PORT,
|
|
PROXY_COUNTRY: process.env.PROXY_COUNTRY,
|
|
PROXY_STATE: process.env.PROXY_STATE,
|
|
PROXY_CITY: process.env.PROXY_CITY,
|
|
PROXY_ZIP: process.env.PROXY_ZIP,
|
|
PROXY_SESSION_DURATION_MINUTES: process.env.PROXY_SESSION_DURATION_MINUTES,
|
|
},
|
|
// Crash reporter (opt-in, reports sent to Cloudflare Worker relay)
|
|
crashReportEnabled: process.env.CAMOFOX_CRASH_REPORT_ENABLED !== 'false',
|
|
crashReportUrl: process.env.CAMOFOX_CRASH_REPORT_URL || '',
|
|
crashReportRepo: process.env.CAMOFOX_CRASH_REPORT_REPO,
|
|
crashReportRateLimit: parseInt(process.env.CAMOFOX_CRASH_REPORT_RATE_LIMIT, 10) || 10,
|
|
crashReporterConfig: readCrashReporterConfig(),
|
|
sentryDsn: process.env.SENTRY_DSN || '',
|
|
};
|
|
}
|
|
|
|
export { loadConfig };
|