Set spec.profile explicitly. Use Development only for disposable evaluation. Use Hardened for production after
every required trust, identity, storage, and network dependency is ready.
Compare the profiles
| Surface | Development | Hardened |
|---|---|---|
| Intended use | Local evaluation, CI, and disposable environments | Production and production-like validation |
| Replicas | One or more | At least three voters |
| TLS | Operator-managed, External, or ACME | External or ACME, with TLS enabled |
| Unseal | Static or external | Explicit non-static provider |
| Initialization | Standard init or self-init | Self-init with a non-empty request list |
| Root token | Can be stored in an operator-managed Secret | Self-init revokes the bootstrap root token |
| Image verification | Optional; Warn or Block when enabled | Enabled for OpenBao and helper images; Warn and explicit disablement are rejected |
| Network and runtime escape hatches | Permitted where the API supports them | Broad or insecure forms are rejected |
Development is not a less complete spelling of Hardened. The profile changes admission, runtime readiness, image
verification, bootstrap credential handling, and Raft Autopilot defaults.
Create a disposable evaluation cluster
This manifest is complete enough for the default operator contract when the namespace is onboarded and a default StorageClass exists.
Declare a Development cluster
apiVersion: openbao.org/v1alpha1
kind: OpenBaoCluster
metadata:
name: dev-cluster
namespace: openbao-demo
spec:
version: "2.6.1"
profile: Development
replicas: 1
tls:
enabled: true
mode: OperatorManaged
rotationPeriod: "720h"
storage:
size: "10Gi"
deletionPolicy: RetainThe operator defaults an omitted unseal configuration to static and creates the unseal key. Standard initialization can also create an immutable root-token Secret. Protect Kubernetes Secrets, etcd encryption, logs, support bundles, and backups even for evaluation.
Meet the Hardened baseline
Before you create a Hardened cluster, define all of these fields and dependencies:
- Set
profile: Hardened, at least three voters, a supported OpenBao version, and persistent storage. - Set
tls.enabled: trueand choosetls.mode: ExternalorACME. - Configure an explicit non-static unseal provider. Do not put a transit token inline.
- Enable self-init and provide at least one request.
- Create a usable human authentication method, policy, and role before self-init revokes the bootstrap credential.
- Enable operator OIDC bootstrap when backup, upgrade, or restore Jobs will use projected JWT authentication.
- Configure external identity and egress for unseal, issuers, object storage, and other dependencies.
- Test a real login, recovery-key custody, backup, restore, and loss of a voter before go-live.
The exact TLS and unseal fields depend on the provider. Use initialize the cluster and configure unseal to build those parts. Do not publish an incomplete provider-neutral manifest as an executable production example.
Understand enforced restrictions
Hardened admission rejects these configurations:
- TLS disablement, operator-managed TLS, and transit
tlsSkipVerify; - static unseal and inline transit tokens;
- fewer than three voters;
- self-init without requests;
- disabled image verification or
failurePolicy: Warnfor OpenBao or operator helper images; - root user or group overrides, root supplemental groups, unconfined seccomp, sysctls, and Windows pod options;
- listener TLS disablement and the dangerous runtime flags
detectDeadlocks,rawStorageEndpoint,introspectionEndpoint, andunsafeAllowAPIAuditCreation; - raw
network.ingressRules, wildcard trusted peers, and egress rules without explicit peers and ports; - backup storage without an explicit Secret, workload identity, or S3 role ARN;
- insecure backup or ServiceMonitor TLS, and Gateway backend HTTP unless TLS passthrough is enabled.
When backup or pre-upgrade snapshots are enabled, Hardened also requires non-empty egress rules. Custom image trust roots and custom executables require their delegated API permissions.
Use image verification defaults deliberately
When both verification blocks are omitted from a Hardened cluster, the operator enables verification for the main OpenBao image and operator helper images. Official images use the built-in official keyless identity defaults. Unknown or mirrored repositories need an explicit public key or keyless issuer and subject.
Use separate configuration blocks because helper-image verification does not inherit the main-image settings:
Set explicit image verification
spec:
imageVerification:
enabled: true
failurePolicy: Block
issuer: "https://token.actions.githubusercontent.com"
subject: "<expected OpenBao release workflow identity>"
operatorImageVerification:
enabled: true
failurePolicy: Block
issuer: "https://token.actions.githubusercontent.com"
subject: "<expected operator release workflow identity>"Only add explicit trust identities after verifying the exact image publisher. In Hardened, warning-only verification is not a transition mode; admission rejects it.
Add AppArmor only when the platform supports it
Set spec.workloadHardening.appArmorEnabled: true to request the runtime-default AppArmor profile on OpenBao
StatefulSets and the built-in backup and upgrade Jobs. Restore and custom validation-hook Jobs do not currently
receive this setting. It remains opt-in because unsupported nodes would leave the affected workload unschedulable;
use platform policy for the remaining Job surfaces.
Verify the effective profile
Inspect profile and readiness
kubectl -n <namespace> get openbaocluster <name> \
-o jsonpath='{.spec.profile}{"\n"}{range .status.conditions[*]}{.type}={.status}{"\t"}{.reason}{"\n"}{end}'Read the exact failed condition and admission message. ProductionReady=True is useful operator evidence, but it does
not prove that a human login or external dependency works end to end.
Continue with initialization.