Overview
Configuration Reference
Format: HOCON (Human-Optimized Config Object Notation)
Override Priority
Section titled “Override Priority”Settings are resolved in this order (highest to lowest):
- CLI flags (
-r,--readonly,--config, etc.) - System properties (
-Dkey=valueor-DKEY=VALUE) - SCRIBE_* env vars (
SCRIBE_LDAP_URL,SCRIBE_DATABASE_PASSWORD, etc.) - Standard env vars (
OTEL_*,POSTGRES_*, etc. where supported) - This config file (values defined below)
- Built-in defaults
Environment Variables
Section titled “Environment Variables”SCRIBE_* variables follow the config path with dots → underscores. Some frequently-tuned settings have shorter aliases.
| Config path | Environment variable |
|---|---|
log.level | SCRIBE_LOG_LEVEL |
concurrency | SCRIBE_CONCURRENCY |
ldap.url | SCRIBE_LDAP_URL |
ldap.max-size-limit | SCRIBE_LDAP_MAX_SIZE_LIMIT |
monitoring.hints.enabled | SCRIBE_HINTS_ENABLED (alias) |
database.url | SCRIBE_DATABASE_URL |
database.password | SCRIBE_DATABASE_PASSWORD |
database.max-pool-size | SCRIBE_DATABASE_MAX_POOL_SIZE |
monitoring.prometheus.enabled | SCRIBE_PROMETHEUS_ENABLED (alias) |
monitoring.traces.enabled | SCRIBE_TRACES_ENABLED |
monitoring.traces.endpoint | OTEL_EXPORTER_OTLP_*, MONITORING_TRACING_OTLP_URL, SCRIBE_TRACES_ENDPOINT |
monitoring.traces.headers | OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS, MONITORING_TRACING_HEADERS, SCRIBE_TRACES_HEADERS |
The ${?VAR} syntax substitutes VAR if defined, otherwise keeps the previous value. When multiple assignments exist, the last one wins.
Value Formats
Section titled “Value Formats”| Type | Examples |
|---|---|
| Booleans | true, false, yes, no, on, off |
| Durations | 500ms, 5s, 30m, 1h, 2d |
| Sizes | 1k, 2m, 3g (bytes) |
| Numbers | 42, 3.14 (no quotes) |
| Strings | "quoted" or unquoted-simple |
Substitution Behavior
Section titled “Substitution Behavior”When ${?VAR} is used WITHOUT a preceding default, the key is undefined if VAR is not set. This allows runtime overrides to fill in values.
When a concrete default precedes ${?VAR}, that default “pins” the value:
key = "default" # Key is always definedkey = ${?SCRIBE_KEY} # Only overrides if SCRIBE_KEY is setAdvanced: CONFIG_FORCE_*
Section titled “Advanced: CONFIG_FORCE_*”With -Dconfig.override_with_env_vars=true, any config key can be overridden using CONFIG_FORCE_* environment variables:
CONFIG_FORCE_a_b__c___d→ config keya.b-c_d- Name mangling:
_→.,__→-,___→_
Config File Location
Section titled “Config File Location”The application searches for the config file in order:
- CLI:
--config /path/to/identity-scribe.conf - System property:
-Dconfig.file=... - Env var:
SCRIBE_CONFIG_FILE(preferred) - Env var:
CONFIG_FILE(fallback) - CWD:
identity-scribe.conf - CWD:
config/identity-scribe.conf - Next to binary:
./identity-scribe.conf - Next to binary:
./config/identity-scribe.conf
Configuration Inheritance
Section titled “Configuration Inheritance”Some sections support automatic inheritance:
| Path | Inherits from |
|---|---|
http.sockets.<name> | http |
ldap.ssl, http.ssl | ssl |
retry.services | retry |
auth.bearer.cache | auth.cache |
auth.ropc.cache | auth.cache |
auth.ldap.cache | auth.cache |
channels.rest.ui | openapi.ui |
monitoring.observe.ui | openapi.ui |
For inheritable sections, just override what differs:
http.sockets.internal { port = 9001 concurrency-limit.max-limit = 50}
auth.cache.ttl = 10m # All auth caches inherit thisauth.ropc.cache.ttl = 5m # Override just ROPC
openapi.ui.theme = "moon" # All UIs inherit thisExtending Default Values
Section titled “Extending Default Values”HOCON lets you customize defaults without copying them. Use these patterns to keep configs short and maintainable.
Append to arrays (+=)
Section titled “Append to arrays (+=)”Add items after existing defaults:
# Single itemmonitoring.log.rules += { action = include, name = "Audit.*" }
# Multiple items (use ${path} [...] pattern, not += [...])monitoring.log.rules = ${monitoring.log.rules} [ { action = include, name = "Debug.*" } { action = exclude, name = "Noisy.*", where = "duration.seconds<=10ms" }]
# Works for any arrayhttp.cors.allow-origins += "http://localhost:3000"ssl.cipher-suites += "TLS_AES_256_GCM_SHA384"Prepend to arrays
Section titled “Prepend to arrays”Place items before defaults. For log rules, earlier items take priority:
# Your rule first, then defaultsmonitoring.log.rules = [ { action = include, name = "Critical.*" }] ${monitoring.log.rules}
# Multiple prepended itemsmonitoring.log.rules = [ { action = include, name = "Security.*" } { action = include, name = "Audit.*" }] ${monitoring.log.rules}Prepend and append together
Section titled “Prepend and append together”Wrap defaults with items on both sides:
monitoring.log.rules = [ # High priority (evaluated first) { action = include, name = "Critical.*" } { action = include, name = "Security.*" }] ${monitoring.log.rules} [ # Low priority (evaluated after defaults) { action = exclude, name = "Verbose.*", where = "duration.seconds<=5s" }]Result: your prepended rules, then defaults, then your appended rules.
Merge objects
Section titled “Merge objects”Objects merge automatically. Specify only what changes:
# Change just the port; inherit host, ssl, cors, etc.http.sockets.admin { port = 9001 }
# Override nested values without touching siblingsmonitoring.log { format = "json" # sample-rate, rules, childs keep their defaults}Inherit with overrides (${path})
Section titled “Inherit with overrides (${path})”Reference another config section and override specific values:
# Start with global SSL, change just the certchannels.rest.ssl = ${ssl} { cert = "/path/to/rest.crt" }
# Inherit parent cache settings, extend TTLauth.bearer.cache = ${auth.cache} { ttl = 10m }The ? in ${?path} makes substitution optional—if the path doesn’t exist, the block is skipped rather than failing.
Inheritance chains
Section titled “Inheritance chains”These settings cascade automatically. Override at any level:
| Setting path | Inherits from |
|---|---|
http.sockets.<name>.ssl | http.ssl → ssl |
http.sockets.<name>.cors | http.cors |
auth.bearer.cache | auth.cache |
auth.ropc.cache | auth.cache |
auth.ldap | ldap |
channels.*.ui | openapi.ui |
transcribes.<name>.ldap | ldap |
Avoid copying defaults
Section titled “Avoid copying defaults”Don’t copy entire arrays just to add items:
# BAD: duplicates 11 default rules, breaks on upgradesmonitoring.log.rules = [ { action = exclude, name = "LDAP.*", ... } { action = exclude, where = "scribe.result=ok ..." } # ... 9 more copied rules ... { action = include, name = "MyCustom.*" } # Only this is new]
# GOOD: append what's newmonitoring.log.rules += { action = include, name = "MyCustom.*" }Copied arrays miss new defaults on upgrade and bloat config files.