Skip to content

Configuration

Architecture

ContextUnity uses a single config factory (load_service_config) shared by all services and the CLI. The factory merges config files, .env, and environment/credentials overrides with strict precedence rules and automatic validation.

Precedence (highest wins)

Programmatic overrides (extra_env) ← highest priority (compound list parsing/edge cases)
└── Per-service env/creds mappings ← custom service env variables
└── Shared env/creds mappings ← SHARED_ENV_MAPPINGS (logging, redis, endpoints)
└── Config file (YAML/TOML) ← source of truth for non-secret settings
└── Class defaults ← Pydantic model defaults (lowest)

Config File Resolution

When load_service_config resolves the config file for a given {service_name}:

1. CU_{SERVICE}_CONFIG_FILE ← explicit file path (highest)
2. CU_CONFIG_DIR/{service}.yml ← explicit directory override
3. fallback_dirs/{service}.yml ← fallback directories (CWD for services; CWD/.contextunity/ & ~/.contextunity/ for CLI)
4. /etc/contextunity/{service}.yml ← system-wide fallback (lowest)

In production, Ansible deploys config files to the service CWD (/opt/contextunity/{service}/{service}.yml), so they are resolved at step 3. The /etc/contextunity/ path exists only as a last-resort fallback.

CU_CONFIG_DIR overrides fallback_dirs when set. .env files are loaded via python-dotenv from the Current Working Directory (CWD) on startup for developer convenience, regardless of the config directory path.

Security Automated Strip

To prevent accidental leakage of credentials, _load_config_file() automatically scans the loaded YAML/TOML data and strips out any keys matching _SECRET_KEYS (e.g. security, private_key, secret_key, api_key, password, etc.) before validating against Pydantic models. All secrets must be loaded via credentials/environment variables.

Execution Contexts

Services

Services run independently. They look for their own configuration files (e.g. brain.yml, router.yml) using the resolution chain.

Terminal window
# Standalone run from services/brain/
uv run contextbrain serve

Services are completely independent from contextunity.yml, which belongs exclusively to the CLI context.

CLI

The CLI reads contextunity.yml (platform config) via its own fallback search chain.

Terminal window
# Initializes target-specific configuration
contextunity config init
# Displays resolved config with automatic secret masking
contextunity config show

The CLI supervisor reads platform-wide settings (such as redis and shield details) from contextunity.yml and propagates them as environment variables to the child processes of the services. These settings are then picked up by the services’ SHARED_ENV_MAPPINGS.


Shared Platform Configuration

All services inherit platform-wide configuration settings defined in SharedConfig. These are mapped from environment variables or systemd credentials using SHARED_ENV_MAPPINGS.

SHARED_ENV_MAPPINGS

Environment VariableConfig PathDescription
LOG_LEVELlog_levelLogging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
LOG_JSONlog_jsonEmit logs in JSON format for telemetry collector
GRPC_REUSE_PORTgrpc_reuse_portEnable SO_REUSEPORT for gRPC server sockets
REDIS_ENABLEDredis.enabledToggle Redis connection for mesh discovery
REDIS_URLredis.urlRedis connection URL (e.g. redis://localhost:6379/0)
SERVICE_NAMEservice_nameService identifier for observability
SERVICE_VERSIONservice_versionService version for observability
CU_PLATFORMcu_platformTarget platform deployment name
GRPC_TLS_ENABLEDtls_enabledEnable gRPC transport security (mTLS)
GRPC_TLS_CA_CERTtls_ca_certPath to TLS CA certificate file
GRPC_TLS_CLIENT_CERTtls_client_certPath to TLS client certificate file
GRPC_TLS_CLIENT_KEYtls_client_keyPath to TLS client key file
GRPC_TLS_SERVER_CERTtls_server_certPath to TLS server certificate file
GRPC_TLS_SERVER_KEYtls_server_keyPath to TLS server key file
GRPC_TLS_REQUIRE_CLIENT_AUTHtls_require_client_authRequire client certificate verification (mTLS)
CU_ROUTER_GRPC_URLrouter_urlContextRouter gRPC connection endpoint
CU_BRAIN_GRPC_URLbrain_urlContextBrain gRPC connection endpoint
CU_SHIELD_GRPC_URLshield_urlContextShield gRPC connection endpoint
CU_WORKER_GRPC_URLworker_urlContextWorker gRPC connection endpoint
TEMPORAL_HOSTtemporal_hostHostname and port of the Temporal cluster
CU_MANIFEST_PATHmanifest_pathPath to service manifest metadata file
CU_LOCAL_MODElocal_modeRun in local standalone mode ( Huey worker / SQLite)
REDIS_SECRET_KEYsecurity.redis_secret_keyEncryption key for project secrets in Redis
CU_PROJECT_SECRETsecurity.project_secretHMAC signature key for Open Source token mode
SHIELD_MASTER_KEYsecurity.shield_master_keyShield security authority master key

Adding New Config Options

To extend ContextUnity configuration:

  1. Add Pydantic Fields: Add fields and default values to SharedConfig (in packages/core/src/contextunity/core/config/models.py) or a specific ServiceConfig subclass.
  2. Define Mappings:
    • For platform-wide parameters, register the mapping in SHARED_ENV_MAPPINGS in factory.py:
      "MY_NEW_OPTION": "my_new_option",
    • For service-specific parameters, register the mapping in the service’s custom env_mappings dictionary during the load_service_config call.
  3. CI & Examples: Update the service’s {service}.yaml.example files and write unit tests verifying correct loading.

Secrets & Systemd Credentials

All sensitive credentials (API keys, DB connection strings, certificates) must bypass the configuration file layer entirely. They are resolved via _read_credential(key.lower()), which operates under a unified priority hierarchy:

systemd-creds ($CREDENTIALS_DIRECTORY/{key}) ← highest priority (Production)
└── Environment Variable (${KEY_UPPER}) ← developer fallback (Development)
└── Explicit fallback value ← lowest priority

Automated Mapping

Service code does not call _read_credential manually for mapped settings. Instead, configurations declare mapping tables (like SHARED_ENV_MAPPINGS or service-specific env_mappings). The config factory automatically traverses these tables, invokes _read_credential() for each mapped key, and applies the result to the nested Pydantic fields.

Managed Secrets Inventory

ServiceMapped Key (lower)Env Override VariablePurpose
Shieldshield_master_keySHIELD_MASTER_KEYMaster key for PKI token signing
Shieldshield_encryption_keySHIELD_ENCRYPTION_KEYEncryption key for DB payload storage
Routeropenai_api_keyOPENAI_API_KEYOpenAI API access key
Routerinception_api_keyINCEPTION_API_KEYInception API access key
Routerlangfuse_secret_keyLANGFUSE_SECRET_KEYObservability secret API key
Brainbrain_database_urlBRAIN_DATABASE_URLPostgreSQL connection URL with password
Viewdjango_secret_keyDJANGO_SECRET_KEYDjango session key
Allredis_secret_keyREDIS_SECRET_KEYRedis payload encryption key
Allcu_project_secretCU_PROJECT_SECRETContextToken signature verification key