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.