From 75e87b659220f597a6db0cbc9e81022e13af898e Mon Sep 17 00:00:00 2001 From: mrbeandev Date: Mon, 16 Feb 2026 12:19:23 +0530 Subject: [PATCH] fix(deploy): prevent Docker ENV vars from overriding JSON config The root cause: Go's env.Parse() in LoadConfig reads PICOCLAW_* environment variables AFTER loading config.json, silently overwriting user-provided values. Dockerfile.coolify had hardcoded Gemini defaults (PICOCLAW_AGENTS_DEFAULTS_PROVIDER=gemini) baked into the image layer, so even when config.json correctly said 'vllm', the env vars won. Fix: - entrypoint-coolify.sh: When using PICOCLAW_CONFIG_JSON (Method 1), or mounted config (Method 2), unset all PICOCLAW_* env vars before calling picoclaw so the JSON file is the single source of truth. - docker-compose-coolify.yml: Remove hardcoded gemini defaults from agent and doctor services. - Updated docs header to recommend PICOCLAW_CONFIG_JSON as primary. --- docker-compose-coolify.yml | 17 ++++++++++------- entrypoint-coolify.sh | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/docker-compose-coolify.yml b/docker-compose-coolify.yml index 1b6107080..6f03e08b3 100644 --- a/docker-compose-coolify.yml +++ b/docker-compose-coolify.yml @@ -9,12 +9,15 @@ # 4. Add environment variables in Coolify's UI (see below) # 5. Deploy! # -# REQUIRED ENVIRONMENT VARIABLES (set in Coolify UI): +# RECOMMENDED: Use PICOCLAW_CONFIG_JSON for full control: +# PICOCLAW_CONFIG_JSON — Full JSON config (overrides everything below) +# +# ALTERNATIVE: Individual environment variables: # GEMINI_API_KEY — Your Gemini API key # # OPTIONAL ENVIRONMENT VARIABLES: -# LLM_PROVIDER — LLM provider (default: gemini) -# LLM_MODEL — Model name (default: gemini-2.5-flash-lite) +# LLM_PROVIDER — LLM provider (e.g. gemini, vllm, openrouter) +# LLM_MODEL — Model name (e.g. gemini-2.5-flash-lite) # TELEGRAM_BOT_TOKEN — Telegram bot token # DISCORD_BOT_TOKEN — Discord bot token # OPENROUTER_API_KEY — OpenRouter API key @@ -124,8 +127,8 @@ services: profiles: - agent environment: - - PICOCLAW_AGENTS_DEFAULTS_PROVIDER=${LLM_PROVIDER:-gemini} - - PICOCLAW_AGENTS_DEFAULTS_MODEL=${LLM_MODEL:-gemini-2.5-flash-lite} + - PICOCLAW_AGENTS_DEFAULTS_PROVIDER=${LLM_PROVIDER:-} + - PICOCLAW_AGENTS_DEFAULTS_MODEL=${LLM_MODEL:-} - PICOCLAW_PROVIDERS_GEMINI_API_KEY=${GEMINI_API_KEY:-} - PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-} - PICOCLAW_PROVIDERS_OPENAI_API_KEY=${OPENAI_API_KEY:-} @@ -151,8 +154,8 @@ services: profiles: - doctor environment: - - PICOCLAW_AGENTS_DEFAULTS_PROVIDER=${LLM_PROVIDER:-gemini} - - PICOCLAW_AGENTS_DEFAULTS_MODEL=${LLM_MODEL:-gemini-2.5-flash-lite} + - PICOCLAW_AGENTS_DEFAULTS_PROVIDER=${LLM_PROVIDER:-} + - PICOCLAW_AGENTS_DEFAULTS_MODEL=${LLM_MODEL:-} - PICOCLAW_PROVIDERS_GEMINI_API_KEY=${GEMINI_API_KEY:-} - TZ=${TZ:-UTC} volumes: diff --git a/entrypoint-coolify.sh b/entrypoint-coolify.sh index 16f8e2505..373dcfbd4 100644 --- a/entrypoint-coolify.sh +++ b/entrypoint-coolify.sh @@ -23,6 +23,17 @@ mkdir -p "${CONFIG_DIR}" if [ -n "${PICOCLAW_CONFIG_JSON}" ]; then echo "📝 Using config from PICOCLAW_CONFIG_JSON env var" echo "${PICOCLAW_CONFIG_JSON}" > "${CONFIG_FILE}" + + # CRITICAL: Unset all PICOCLAW_* env vars (except PICOCLAW_CONFIG_JSON) + # so that Go's env.Parse() does NOT override values from the JSON file. + # Without this, Dockerfile ENV defaults (e.g. PICOCLAW_AGENTS_DEFAULTS_PROVIDER=gemini) + # would silently overwrite the user's JSON config every time. + for var in $(env | grep '^PICOCLAW_' | cut -d= -f1); do + if [ "$var" != "PICOCLAW_CONFIG_JSON" ]; then + unset "$var" + fi + done + exec picoclaw "$@" fi @@ -36,6 +47,12 @@ fi if [ -f "/config/config.json" ]; then echo "📝 Using mounted config from /config/config.json" cp /config/config.json "${CONFIG_FILE}" + + # Same protection as Method 1: unset PICOCLAW_* env vars + for var in $(env | grep '^PICOCLAW_' | cut -d= -f1); do + unset "$var" + done + exec picoclaw "$@" fi