Keep the operator defaults until measured requirements justify a change. Server-runtime tuning is not a prerequisite for the first cluster.
Choose the correct configuration surface
| Surface | Controls |
|---|---|
spec.configuration | UI, log level, cache, lease, listener, logging, Raft, and plugin-runtime settings |
spec.audit | Declarative file, HTTP, syslog, or socket audit devices |
spec.plugins | Declarative auth, secret, database, or KMS plugin declarations |
spec.configuration.raft.autopilot | Raft health thresholds, quorum bounds, and dead-peer cleanup |
External exposure, TLS, NetworkPolicy, and observability are separate service-boundary decisions. File audit storage is owned by the storage guide.
Tune the core runtime
Use spec.configuration for a specific OpenBao requirement, not as a copied collection of arbitrary values.
Set selected server options
spec:
configuration:
ui: true
logLevel: info
defaultLeaseTTL: "24h"
maxLeaseTTL: "720h"
raft:
performanceMultiplier: 2| Field | Change it when |
|---|---|
ui | The built-in UI is intentionally enabled or disabled; route exposure is configured elsewhere |
logLevel and logging | Operational evidence requires a different level, format, file, or rotation policy |
cacheSize and disableCache | Profiling and workload behavior justify changing cache behavior |
defaultLeaseTTL and maxLeaseTTL | Application lease policy requires explicit bounds |
raft.performanceMultiplier | Measured disk or network latency justifies slower Raft timing |
listener.proxyProtocolBehavior | The selected load balancer sends Proxy Protocol and the trust boundary is understood |
Valid Proxy Protocol values are use_always, allow_any, and deny_unauthorized. Do not use the upstream-looking
value use_proxy_protocol; the CRD rejects it. Keep listener TLS aligned with the later external-access design, and do
not set listener.tlsDisable: true on Hardened clusters.
The Hardened profile also rejects detectDeadlocks, rawStorageEndpoint, introspectionEndpoint, and
unsafeAllowAPIAuditCreation. Those flags expose debugging or unsafe runtime surfaces rather than normal operations.
Configure audit devices
Declare audit devices in spec.audit when they must exist as part of the cluster configuration. Supported structured
types are file, HTTP, syslog, and socket.
Write file audit records to shared storage
spec:
auditFileStorage:
mode: ManagedPVC
size: "20Gi"
storageClassName: rwx-encrypted
audit:
- type: file
path: secure-audit
description: Secure audit logging
fileOptions:
filePath: /openbao/audit/audit.jsonl
mode: "0600"The structured field is fileOptions.filePath in camel case. File paths must live under the effective
auditFileStorage.mountPath, which defaults to /openbao/audit.
| Type | Structured fields |
|---|---|
| File | filePath and optional octal mode |
| HTTP | uri and optional headers shaped as map[string][]string |
| Syslog | Optional facility and tag |
| Socket | Optional address, socketType, and writeTimeout |
The generic options object remains available for flat string-valued advanced options. Structured options take
precedence and reject nested objects or arrays except the typed HTTP headers field.
Audit storage is a collector handoff and replay buffer. It is not rotation, retention, tamper-proof archival, or a complete collection pipeline.
Register plugins
Use an OCI plugin when OpenBao can download the binary at startup. Use command only when the binary is already in the
runtime image or another deliberately managed path.
Register an OCI plugin
spec:
version: "2.6.1"
configuration:
plugin:
autoDownload: true
downloadBehavior: fail
plugins:
- type: secret
name: example
image: registry.example.com/openbao-plugin-secrets-example
version: v1.0.0
binaryName: openbao-plugin-secrets-example
sha256sum: "<64-character-sha256>"Register a preinstalled plugin
spec:
plugins:
- type: secret
name: local-example
command: openbao-plugin-secrets-example
version: v1.0.0
binaryName: openbao-plugin-secrets-example
sha256sum: "<64-character-sha256>"Plugin requirements:
imageandcommandare mutually exclusive; one is required.- Plugin download settings require OpenBao 2.5.0 or newer.
downloadBehavior: failstops startup after a failed download;continuelogs the failure and continues.argsandenvare used only whenautoRegisteris enabled.- OCI-downloaded binaries use a writable pod-local
emptyDirat/openbao/plugins. It is a cache, not durable storage. - OpenBao’s runtime OCI client needs registry egress and its own authentication. Kubernetes
imagePullSecretscover Kubernetes image pulls, not necessarily plugin downloads inside the container. - An identity selecting a plugin
imageorcommandneeds delegatedusecustomexecutablesauthority on the cluster. - A plugin with
type: kmscan backspec.unseal.type: kmson OpenBao 2.6.0 and later. Its name must matchspec.unseal.kms.pluginName; see Configure unseal.
Understand Raft Autopilot defaults
After initialization, the operator reconciles these effective defaults:
| Setting | Effective default |
|---|---|
deadServerLastContactThreshold | 5m |
lastContactThreshold | 10s |
maxTrailingLogs | 1000 |
serverStabilizationTime | 10s |
Hardened minQuorum | 3 for three voters; all voters when replicas exceed three |
Development minQuorum | Replica count, with a minimum of one |
cleanupDeadServers | true, except it is automatically disabled for a derived quorum below three unless explicitly overridden |
The CRD requires an explicitly configured minQuorum to be at least three. Small Development clusters can still have
a derived value below three; automatic cleanup is then disabled so OpenBao does not reject the configuration.
For self-init clusters, day-2 Autopilot reconciliation requires operator JWT bootstrap. Without
selfInit.oidc.enabled, the operator skips that authenticated reconciliation after initialization. Standard-init
clusters use the operator-managed root-token Secret.
Override Autopilot only after measuring the failure or latency behavior you need to change:
Override Raft Autopilot
spec:
profile: Hardened
replicas: 5
configuration:
raft:
autopilot:
minQuorum: 4
deadServerLastContactThreshold: "10m"
lastContactThreshold: "30s"
maxTrailingLogs: 2000
serverStabilizationTime: "30s"If you set cleanupDeadServers: false, you take manual ownership of dead-peer removal. Treat that as a controlled
operational exception.
Inspect the schema and rendered state
Inspect configuration fields
kubectl explain openbaocluster.spec.configuration
kubectl explain openbaocluster.spec.audit
kubectl explain openbaocluster.spec.pluginsAfter an update, inspect the OpenBaoCluster conditions, generated ConfigMap, StatefulSet revision, Pod events, and
OpenBao logs. A schema-valid option can still be incompatible with the selected OpenBao version or external runtime.