From e2b6879ea2c8be11189bc422a47a221a735478bd Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 7 Jun 2025 08:34:31 +0000 Subject: [PATCH] api/env: log information about dynamic env changes --- api/src/config.js | 7 +++++++ api/src/core/env.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/api/src/config.js b/api/src/config.js index 095780ee..ceac2f6d 100644 --- a/api/src/config.js +++ b/api/src/config.js @@ -12,12 +12,19 @@ export const canonicalEnv = Object.freeze(structuredClone(process.env)); export const setTunnelPort = (port) => env.tunnelPort = port; export const isCluster = env.instanceCount > 1; export const updateEnv = (newEnv) => { + const changes = []; + // tunnelPort is special and needs to get carried over here newEnv.tunnelPort = env.tunnelPort; for (const key in env) { + if (String(env[key]) !== String(newEnv[key])) { + changes.push(key); + } env[key] = newEnv[key]; } + + return changes; } await validateEnvs(env); diff --git a/api/src/core/env.js b/api/src/core/env.js index 35c892f9..37ab36c1 100644 --- a/api/src/core/env.js +++ b/api/src/core/env.js @@ -5,7 +5,7 @@ import { updateEnv, canonicalEnv, env as currentEnv } from "../config.js"; import { FileWatcher } from "../misc/file-watcher.js"; import { isURL } from "../misc/utils.js"; import * as cluster from "../misc/cluster.js"; -import { Yellow } from "../misc/console-text.js"; +import { Green, Yellow } from "../misc/console-text.js"; const forceLocalProcessingOptions = ["never", "session", "always"]; @@ -109,6 +109,8 @@ export const validateEnvs = async (env) => { if (env.externalProxy && env.freebindCIDR) { throw new Error('freebind is not available when external proxy is enabled') } + + return env; } const reloadEnvs = async (contents) => { @@ -136,14 +138,34 @@ const reloadEnvs = async (contents) => { ...newEnvs, }; - const parsed = loadEnvs(candidate); - await validateEnvs(parsed); - updateEnv(parsed); + const parsed = await validateEnvs( + loadEnvs(candidate) + ); + cluster.broadcast({ env_update: resolvedContents }); + return updateEnv(parsed); } const wrapReload = (contents) => { reloadEnvs(contents) + .then(changes => { + if (changes.length === 0) { + return; + } + + console.log(`${Green('[✓]')} envs reloaded successfully!`); + for (const key of changes) { + const value = currentEnv[key]; + const isSecret = key.toLowerCase().includes('apikey') + || key.toLowerCase().includes('secret'); + + if (!value) { + console.log(` removed: ${key}`); + } else { + console.log(` changed: ${key} -> ${isSecret ? '***' : value}`); + } + } + }) .catch((e) => { console.error(`${Yellow('[!]')} Failed reloading environment variables at ${new Date().toISOString()}.`); console.error('Error:', e);