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 override3. 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.
# Standalone run from services/brain/uv run contextbrain serveServices 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.
# Initializes target-specific configurationcontextunity config init
# Displays resolved config with automatic secret maskingcontextunity config showThe 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 Variable | Config Path | Description |
|---|---|---|
LOG_LEVEL | log_level | Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
LOG_JSON | log_json | Emit logs in JSON format for telemetry collector |
GRPC_REUSE_PORT | grpc_reuse_port | Enable SO_REUSEPORT for gRPC server sockets |
REDIS_ENABLED | redis.enabled | Toggle Redis connection for mesh discovery |
REDIS_URL | redis.url | Redis connection URL (e.g. redis://localhost:6379/0) |
SERVICE_NAME | service_name | Service identifier for observability |
SERVICE_VERSION | service_version | Service version for observability |
CU_PLATFORM | cu_platform | Target platform deployment name |
GRPC_TLS_ENABLED | tls_enabled | Enable gRPC transport security (mTLS) |
GRPC_TLS_CA_CERT | tls_ca_cert | Path to TLS CA certificate file |
GRPC_TLS_CLIENT_CERT | tls_client_cert | Path to TLS client certificate file |
GRPC_TLS_CLIENT_KEY | tls_client_key | Path to TLS client key file |
GRPC_TLS_SERVER_CERT | tls_server_cert | Path to TLS server certificate file |
GRPC_TLS_SERVER_KEY | tls_server_key | Path to TLS server key file |
GRPC_TLS_REQUIRE_CLIENT_AUTH | tls_require_client_auth | Require client certificate verification (mTLS) |
CU_ROUTER_GRPC_URL | router_url | ContextRouter gRPC connection endpoint |
CU_BRAIN_GRPC_URL | brain_url | ContextBrain gRPC connection endpoint |
CU_SHIELD_GRPC_URL | shield_url | ContextShield gRPC connection endpoint |
CU_WORKER_GRPC_URL | worker_url | ContextWorker gRPC connection endpoint |
TEMPORAL_HOST | temporal_host | Hostname and port of the Temporal cluster |
CU_MANIFEST_PATH | manifest_path | Path to service manifest metadata file |
CU_LOCAL_MODE | local_mode | Run in local standalone mode ( Huey worker / SQLite) |
REDIS_SECRET_KEY | security.redis_secret_key | Encryption key for project secrets in Redis |
CU_PROJECT_SECRET | security.project_secret | HMAC signature key for Open Source token mode |
SHIELD_MASTER_KEY | security.shield_master_key | Shield security authority master key |
Adding New Config Options
To extend ContextUnity configuration:
- Add Pydantic Fields: Add fields and default values to
SharedConfig(inpackages/core/src/contextunity/core/config/models.py) or a specificServiceConfigsubclass. - Define Mappings:
- For platform-wide parameters, register the mapping in
SHARED_ENV_MAPPINGSinfactory.py:"MY_NEW_OPTION": "my_new_option", - For service-specific parameters, register the mapping in the service’s custom
env_mappingsdictionary during theload_service_configcall.
- For platform-wide parameters, register the mapping in
- CI & Examples: Update the service’s
{service}.yaml.examplefiles 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 priorityAutomated 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
| Service | Mapped Key (lower) | Env Override Variable | Purpose |
|---|---|---|---|
| Shield | shield_master_key | SHIELD_MASTER_KEY | Master key for PKI token signing |
| Shield | shield_encryption_key | SHIELD_ENCRYPTION_KEY | Encryption key for DB payload storage |
| Router | openai_api_key | OPENAI_API_KEY | OpenAI API access key |
| Router | inception_api_key | INCEPTION_API_KEY | Inception API access key |
| Router | langfuse_secret_key | LANGFUSE_SECRET_KEY | Observability secret API key |
| Brain | brain_database_url | BRAIN_DATABASE_URL | PostgreSQL connection URL with password |
| View | django_secret_key | DJANGO_SECRET_KEY | Django session key |
| All | redis_secret_key | REDIS_SECRET_KEY | Redis payload encryption key |
| All | cu_project_secret | CU_PROJECT_SECRET | ContextToken signature verification key |