# Configuration reference

Configuration precedence is defaults, YAML passed with `--config`, `KEYSTONE_GATEWAY_*` environment variables, then `serve` flags. Convert a dotted YAML key to an environment variable by uppercasing it and replacing dots with underscores (for example `KEYSTONE_GATEWAY_LEASES_DEFAULT_TTL_SECONDS`). Every key also has a `--` flag with dots replaced by hyphens. Unknown YAML keys are rejected. Restart to apply every configuration or license change; V1 has no reload.

Required means required in the stated deployment shape. Empty defaults require operator input.

<table><caption class="sr-only">Configuration reference</caption><thead><tr><th scope="col">YAML key</th><th scope="col">Default</th><th scope="col">Required / valid values</th><th scope="col">Effect</th></tr></thead><tbody><tr><td><code>gateway_id</code></td><td>—</td><td>always; logical ID</td><td>Signed deployment identity</td></tr><tr><td><code>api.https.enabled</code> / <code>api.http.enabled</code></td><td><code>false</code> / <code>false</code></td><td>exactly one true</td><td>Client transport</td></tr><tr><td><code>api.https.listen</code>, <code>advertise_url</code></td><td>—</td><td>HTTPS; host:port, <code>https://</code> URL</td><td>Bind and client address</td></tr><tr><td><code>api.https.server_cert_file</code>, <code>server_key_file</code></td><td>—</td><td>HTTPS</td><td>Server TLS files</td></tr><tr><td><code>api.https.client_ca_file</code>, <code>principal_mappings_file</code></td><td>—</td><td>HTTPS + <code>mtls</code></td><td>Client trust and CN mapping</td></tr><tr><td><code>api.http.listen</code>, <code>advertise_url</code></td><td>—</td><td>HTTP; host:port, <code>http://</code> URL</td><td>Bind and client address</td></tr><tr><td><code>api.http.allow_insecure_http</code></td><td><code>false</code></td><td>true for HTTP</td><td>Explicit plaintext acknowledgement</td></tr><tr><td><code>api.http.bearer_credentials_file</code></td><td>—</td><td>HTTP + <code>bearer</code></td><td>SHA-256 credential mappings</td></tr><tr><td><code>api.auth.mode</code></td><td>—</td><td><code>none</code>, <code>bearer</code>, <code>mtls</code></td><td>Authentication policy</td></tr><tr><td><code>api.auth.principal_id</code>, <code>api.auth.allowed_license_type</code>, <code>api.auth.operator</code></td><td>—, —, <code>false</code></td><td>only <code>none</code>; type <code>phocol</code> or <code>lmc_exporter</code></td><td>One shared perimeter-trust principal</td></tr><tr><td><code>storage.directory</code>, <code>encryption_key_file</code></td><td>—</td><td>always</td><td>Encrypted durable state and 32-byte key</td></tr><tr><td><code>storage.snapshot_directory</code></td><td>—</td><td>optional; compatibility only</td><td>Not consumed by V1 runtime; actual HA snapshots are under <code>storage.directory/raft/snapshots</code></td></tr><tr><td><code>storage.peer.replica_id</code>, <code>listen</code>, <code>target</code>, <code>reconcile_listen</code>, <code>reconcile_target</code></td><td>—</td><td>HA only</td><td>Other replica and two peer channels</td></tr><tr><td><code>storage.peer.tls.cert_file</code>, <code>key_file</code>, <code>ca_file</code></td><td>—</td><td>HA only</td><td>Peer mTLS files</td></tr><tr><td><code>license.file</code></td><td>—</td><td>always</td><td>Signed Gateway license</td></tr><tr><td><code>ha.enabled</code></td><td><code>false</code></td><td>boolean</td><td>Two-node mode</td></tr><tr><td><code>ha.replica_id</code></td><td>—</td><td>always; logical ID</td><td>This replica’s signed identity</td></tr><tr><td><code>ha.bootstrap_expect</code></td><td><code>1</code></td><td><code>1</code> standalone; <code>2</code> HA</td><td>Raft voter count</td></tr><tr><td><code>ha.peer_loss_timeout_seconds</code></td><td><code>5</code></td><td>&gt;0</td><td>Delay before degraded-active</td></tr><tr><td><code>ha.operator_recovery_enabled</code></td><td><code>false</code></td><td>boolean; reserved</td><td>Compatibility setting; no V1 operational effect</td></tr><tr><td><code>leases.default_ttl_seconds</code></td><td><code>120</code></td><td>min ≤ default ≤ max</td><td>Requested default lease length</td></tr><tr><td><code>leases.min_ttl_seconds</code>, <code>max_ttl_seconds</code></td><td><code>30</code>, <code>300</code></td><td>&gt;0</td><td>Lease TTL bounds</td></tr><tr><td><code>leases.max_clock_skew_seconds</code></td><td><code>5</code></td><td>≥0</td><td>HA leadership skew bound</td></tr><tr><td><code>leases.expiry_sweep_seconds</code></td><td><code>15</code></td><td>&gt;0</td><td>Expired-record cleanup interval</td></tr><tr><td><code>telemetry.enabled</code></td><td><code>false</code></td><td>boolean</td><td>Enables customer OTLP export</td></tr><tr><td><code>telemetry.otlp_endpoint</code></td><td>—</td><td>enabled only; no userinfo, query, or fragment</td><td>Collector host/URL; use <code>auth_headers</code> for credentials</td></tr><tr><td><code>telemetry.protocol</code></td><td><code>grpc</code></td><td><code>grpc</code>, <code>http/protobuf</code></td><td>OTLP transport</td></tr><tr><td><code>telemetry.ca_file</code>, <code>auth_headers</code></td><td>empty</td><td>optional</td><td>Collector TLS trust and <code>Name=Value</code> secrets</td></tr><tr><td><code>telemetry.export_timeout_seconds</code></td><td><code>10</code></td><td>enabled; &gt;0</td><td>Shutdown export bound</td></tr><tr><td><code>reports.directory</code></td><td>—</td><td>always</td><td>Report directory configuration</td></tr><tr><td><code>reports.retention_days</code></td><td><code>90</code></td><td>≥0</td><td>Report retention setting</td></tr><tr><td><code>logging.level</code>, <code>logging.format</code></td><td><code>info</code>, <code>json</code></td><td>debug/info/warn/error; json/text</td><td>Structured log output</td></tr></tbody></table>

`reports.directory` is a configuration input; V1’s `report` CLI writes to standard output and the Gateway does not currently create report files or expose a backup/restore CLI. `storage.snapshot_directory` is accepted for configuration compatibility but not used by V1 runtime; see [backup and recovery](https://portal.cjcit.io/knowledge-base/keystone_gateway/0.2/operations/backup-and-recovery/). See [examples](https://portal.cjcit.io/knowledge-base/keystone_gateway/0.2/configuration/examples/), [CLI flags](https://portal.cjcit.io/knowledge-base/keystone_gateway/0.2/reference/cli/), and [security](https://portal.cjcit.io/knowledge-base/keystone_gateway/0.2/security/deployment-security/).

## Principal and license-type cardinality

`api.auth.allowed_license_type` is a scalar used only by the single fixed principal in `api.auth.mode: none`; it accepts `phocol` or `lmc_exporter`, not a list. In `mtls` and `bearer` modes, leave all three fixed-principal fields empty and define callers in `api.https.principal_mappings_file` or `api.http.bearer_credentials_file` instead. Each mapping entry still authorizes exactly one license type. Add separate entries and principal IDs to authorize installations for both types.

Mapping files must contain at least one entry and must not exceed 1 MiB in total; there is no separate maximum number of entries. Common Names and bearer hashes must be unique. Reusing a `principal_id` is accepted only when every occurrence has identical authority. Each mapped license type must be declared by the verified Gateway license or startup fails. See [client authentication](https://portal.cjcit.io/knowledge-base/keystone_gateway/0.2/security/deployment-security/#configure-client-authentication) for complete multi-principal examples.
