// Copyright (c) 2025 Gordon Bolton. MIT License. // // Docker secrets support: if an environment variable named FOO_FILE is set, // read its contents from the file at that path and expose it as FOO. // This follows the standard *_FILE convention used by official Docker images. // // Supported secrets: // COOKIE_SECRET_FILE → COOKIE_SECRET // EMBY_API_KEY_FILE → EMBY_API_KEY // SABNZBD_API_KEY_FILE → SABNZBD_API_KEY (legacy single-instance) // SONARR_API_KEY_FILE → SONARR_API_KEY (legacy single-instance) // RADARR_API_KEY_FILE → RADARR_API_KEY (legacy single-instance) // QBITTORRENT_PASSWORD_FILE → QBITTORRENT_PASSWORD (legacy single-instance) // // For multi-instance JSON arrays the secret values must be embedded in the // JSON string itself; file-based loading is for the legacy single-key format. const fs = require('fs'); const SECRET_MAPPINGS = [ 'COOKIE_SECRET', 'EMBY_API_KEY', 'SABNZBD_API_KEY', 'SONARR_API_KEY', 'RADARR_API_KEY', 'QBITTORRENT_PASSWORD', ]; function loadSecrets() { for (const key of SECRET_MAPPINGS) { const fileEnv = `${key}_FILE`; const filePath = process.env[fileEnv]; if (!filePath) continue; if (process.env[key]) { console.warn(`[Secrets] Both ${key} and ${fileEnv} are set — ${fileEnv} takes precedence`); } try { const value = fs.readFileSync(filePath, 'utf8').trim(); if (!value) { console.warn(`[Secrets] ${fileEnv} points to an empty file: ${filePath}`); continue; } process.env[key] = value; console.log(`[Secrets] Loaded ${key} from ${fileEnv}`); } catch (err) { console.error(`[Secrets] Failed to read ${fileEnv} (${filePath}): ${err.message}`); process.exit(1); } } } module.exports = loadSecrets;