Skip to main content

Environments and Sensitive Runtime Config

Environments — patrón para config sensible: templates, JSON generado y secretos. ↓ Configuration · ⬆ Documentación AITHA

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 (local development) or Ansible Vault (remote servers).

Generated configs​

These files must no longer be versioned:

  • platform/portal/ui/src/config/subsystems.json
  • infrastructure/chat-server/config/mcp_services.json
  • infrastructure/chat-server/config/llm_providers.json
  • infrastructure/chat-server/config/llm_embeddings.json

The versioned sources are their corresponding .template files.

Canonical sources​

  • Shared secrets (local dev): /.env.secrets
  • Non-sensitive config and aliases: /.env
  • Per-stack overrides: <stack>/.env

Remote deployments (servers)​

  • ./infra remote deploy does not sync your local /.env.secrets to servers.
  • Recommended: store server runtime secrets in Ansible Vault as core2_env_secrets and let Ansible render /opt/core2infra/.env.secrets on the server (mode 0600, path controlled by CORE2_REMOTE_REPO_ROOT).
  • Server connection passwords (bootstrap/deploy) are prompted by default; set CORE2_SAVE_REMOTE_PASSWORDS=true if you explicitly want to persist them locally.
  • ./infra sandbox up only provisions a local VM. Secrets still come into play when you later run the normal remote bootstrap / remote deploy flow against that VM.

Root keys used by this flow:

  • GLOBAL_CHATWOOT_PLATFORM_TOKEN
  • GLOBAL_THINGSBOARD_SYSTEM_USER_SECRET
  • GLOBAL_GOOGLE_GENAI_API_KEY
  • GLOBAL_NVIDIA_API_KEY
  • GLOBAL_OPENAI_API_KEY
  • THINGSBOARD_API_BASE_URL
  • THINGSBOARD_ADMIN_USER
  • THINGSBOARD_SYSTEM_USER_DOMAIN
  • CHATWOOT_API_BASE_URL

Operational commands​

Generate .env, missing secrets, and runtime configs:

./infra 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-app no longer edits subsystems.json.
  • The Platform App token is stored in GLOBAL_CHATWOOT_PLATFORM_TOKEN.
  • Runtime config is regenerated afterwards.

ThingsBoard​

  • The portal and chat-server no 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_key is only allowed for safe values like lm-studio, no-key, or placeholders.
  • Fallback to FakeEmbeddings is only allowed with DEV_MODE=true.

n8n​

  • The image is pinned via N8N_VERSION.
  • WEBHOOK_URL is 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:29092 and its wrapper won't start if Kafka is not healthy.
  • data-aggregator validates real TCP connectivity to Kafka.
  • Airflow stops bootstrapping airflow/airflow and loads apache-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.