Environments and Sensitive Runtime Config
Last updated: 2026-03-21
This document defines the operational pattern for sensitive configuration in this repo: version templates, generate runtime JSON outside Git, and resolve secrets from .env.secrets.
Generated configs
These files must no longer be versioned:
platform/portal/ui/src/config/subsystems.jsoninfrastructure/chat-server/config/mcp_services.jsoninfrastructure/chat-server/config/llm_providers.jsoninfrastructure/chat-server/config/llm_embeddings.json
The versioned sources are their corresponding .template files.
Canonical sources
- Shared secrets:
/.env.secrets - Non-sensitive config and aliases:
/.env - Per-stack overrides:
<stack>/.env
Root keys used by this flow:
GLOBAL_CHATWOOT_PLATFORM_TOKENGLOBAL_THINGSBOARD_SYSTEM_USER_SECRETGLOBAL_GOOGLE_GENAI_API_KEYGLOBAL_NVIDIA_API_KEYGLOBAL_OPENAI_API_KEYTHINGSBOARD_API_BASE_URLTHINGSBOARD_ADMIN_USERTHINGSBOARD_SYSTEM_USER_DOMAINCHATWOOT_API_BASE_URL
Operational commands
Generate .env, missing secrets, and runtime configs:
./infra.sh env generate
Regenerate only runtime JSON:
bash deployment/scripts/config-generators/generate-runtime-configs.sh
Scan for secrets in versioned files:
deployment/scripts/scan-secrets.sh
If you use pre-commit, the local hook is defined in .pre-commit-config.yaml.
New behavior
Chatwoot
platform/chatwoot/run.custom.sh platform-appno longer editssubsystems.json.- The Platform App token is stored in
GLOBAL_CHATWOOT_PLATFORM_TOKEN. - Runtime config is regenerated afterwards.
ThingsBoard
- The portal and
chat-serverno longer depend on a fixed password for technical users. - Technical username pattern:
system_<entityId>@<THINGSBOARD_SYSTEM_USER_DOMAIN>. - Technical password is derived via
HMAC-SHA256(GLOBAL_THINGSBOARD_SYSTEM_USER_SECRET, "<scope>:<entityId>").
chat-server / LLMs
- Versioned providers use
api_key_env. - Inline
api_keyis only allowed for safe values likelm-studio,no-key, or placeholders. - Fallback to
FakeEmbeddingsis only allowed withDEV_MODE=true.
n8n
- The image is pinned via
N8N_VERSION. WEBHOOK_URLis now required.- Legacy ThingsBoard exports were sanitized and must be treated as reference material, not an authoritative secrets source.
Applied stack hardening
- Kafka waits for a real ZooKeeper healthcheck.
- ThingsBoard targets
kafka:29092and its wrapper won't start if Kafka is not healthy. data-aggregatorvalidates real TCP connectivity to Kafka.- Airflow stops bootstrapping
airflow/airflowand loadsapache-airflow-providers-influxdb. - Zitadel stops running as root and no longer mounts the whole repo.
- Telegraf syncs its MQTT credentials from the Mosquitto stack.
Remediation still required outside the repo
These changes harden the future, but they do not rotate previously exposed secrets. You still need to rotate:
- the current Chatwoot Platform App token,
- ThingsBoard admin/technical credentials that were used with the prior fixed password,
- any real Google/NVIDIA/OpenAI keys if they were ever committed.