Enable real end-to-end encryption and switch the OpenBao HA deployment from HTTP (Route edge termination) to TLS on the listener, HTTPS Raft, and a reencrypt Route, with cert-manager issuing server and Agent Injector certificates. Follows OpenBao Part 4 — Enabling TLS on OpenShift.
Prerequisites checklist
Confirm these before running steps:
- PRE-01Verify Helm 3+ and install repository
- PRE-08Verify deployment — pods, API, UI, Raft
- Part 3 Helm values baseline (
openbao-values.yamlwithtls_disable = 1) - PRE-11Install cert-manager via the OpenShift Operator
1Confirm the current deployment uses HTTP to the pods (Part 3)
oc get route openbao -n openbao -o jsonpath='{.spec.tls.termination}{"\n"}'→ edge (TLS only between client and Route)
2Issue Self-signed certificates with cert-manager (full YAML in Commands / YAML tab):
→ Self-signed CA Issuer + CA Certificate (
openbao-ca-secret)→ CA Issuer (
openbao-ca-issuer) referencing the CA secret→ Server Certificate (
openbao-server-tls) — include Route host, all service/Raft DNS names, and 127.0.0.1 / ::1 IP SANs→ Injector Certificate (
injector-tls) — match openbao-agent-injector-svc DNS names3Wait until cert-manager reports certificates Ready:
oc get certificate -n openbao→ openbao-ca, openbao-server-tls, injector-certificate: Ready=True
4Export the CA certificate for clients and the Route `destinationCACertificate`
oc get secret openbao-ca-secret -n openbao -o jsonpath='{.data.ca\.crt}' | base64 -d > openbao-ca.crt5Build the TLS Helm values file (`openbao-ha-values-tls.yaml`)
Apply From the Commands / YAML tab**
6The main differences are:
→
global.tlsDisable: false→ Listener
tls_disable = 0 with cert/key paths under /openbao/tls/openbao-server-tls/→ Raft
retry_join uses https:// and leader_ca_cert_file→ Route
termination: reencrypt with destinationCACertificate (CA PEM, no extra blank lines)→ Mount secret
openbao-server-tls; injector certs.secretName: injector-tls and caBundle (base64 CA)7Upgrade the Helm release:
helm upgrade openbao openbao/openbao -n openbao -f openbao-ha-values-tls.yaml8Optional: Trigger restart of the pods:
oc scale statefulset/openbao -n openbao --replicas=0watch oc get pods -n openbao→ Watch until all pods are terminated
oc scale statefulset/openbao -n openbao --replicas=3→ Watch until all pods are 1/1 Ready (openbao-0 may stay 0/1 until unsealed)
9Connect now using the HTTPS endpoint:
oc port-forward openbao-0 8200:8200 -n openbao &export BAO_ADDR='https://127.0.0.1:8200'We need to trust the self-signed certificate. This is optional when you have a valid and trusted CA.
export BAO_CACERT="$PWD/openbao-ca.crt"→ the openbao-ca.crt was exported in Step 5
bao status→
Initialized true (was done during prereqs), Sealed true (because the cluster was restarted)10Unseal `openbao-0` again (repeat 3× with different keys):
oc exec -ti openbao-0 -n openbao -- bao operator unseal11Re-join Raft and re-unseal over HTTPS:
oc exec -ti openbao-1 -n openbao -- bao operator raft join https://openbao-0.openbao-internal:8200repeat 3× with different keys
oc exec -ti openbao-1 -n openbao -- bao operator unsealRepeat join + unseal for openbao-2
→ All three server pods 1/1 Ready
12Verify that all pods are ready:
oc get pods -n openbao→ All pods 1/1 Ready
13Verify Route backend TLS mode:
oc get route openbao -n openbao -o jsonpath='{.spec.tls.termination}{"\n"}'→ reencrypt (not edge)
14Verify API health over HTTPS (Route host — adjust to yours):
curl --cacert openbao-ca.crt https://openbao.apps.cluster.example.com/v1/sys/health | jq→ HTTP 200/429/472/473 with
initialized, sealed, standby fields15Verify Agent Injector webhook (no TLS errors in logs):
oc logs -n openbao -l app.kubernetes.io/name=openbao-agent-injector --tail=20→ No certificate or TLS handshake errors