BoltMCP Installation Docs

Rotating Secrets

Rotate the OIDC client secrets in the boltmcp-oidc Secret and propagate the new values to Keycloak and the pods that use them.

The boltmcp-oidc Secret holds one client secret per confidential Keycloak client that BoltMCP authenticates as. Each value lives in two places: the Kubernetes Secret, which you manage, and the matching client inside Keycloak, which BoltMCP manages. Rotation means changing both. Helm does not watch the Secret's contents, and Kubernetes does not restart pods when a Secret changes, so a rotation is three deliberate steps.

KeyKeycloak clientRestart after rotating
web-client-secretboltmcp-webdeployment/boltmcp-web
mcp-server-client-secretboltmcp-mcp-serverdeployment/boltmcp-mcp-server
rest-api-to-keycloak-client-secretboltmcp-rest-api-to-keycloakdeployment/boltmcp-rest-api
keycloak-reconcile-client-secretboltmcp-keycloak-reconcilenone (used only by the keycloak-reconcile hook Job)

Set Variables

export RELEASE=boltmcp
export NAMESPACE=boltmcp

1. Update the Secret

Generate the new value and patch it into the Secret under the right key. A merge patch against stringData leaves the other keys untouched:

NEW_SECRET=$(openssl rand -hex 32)

kubectl patch secret ${RELEASE}-oidc -n ${NAMESPACE} --type merge -p "{
  \"stringData\": { \"web-client-secret\": \"${NEW_SECRET:?not generated}\" }
}"

If the Secret is populated from an external system (External Secrets Operator, Sealed Secrets, SOPS), change the value at the source instead and wait for the controller to sync it, or force a sync. Either way, confirm the Secret in the cluster carries the new value before continuing:

kubectl get secret ${RELEASE}-oidc -n ${NAMESPACE} \
  -o go-template='{{range $k, $v := .data}}{{$k}}={{len $v}}{{"\n"}}{{end}}'

2. Stamp the new value onto the Keycloak client

Re-run helm upgrade with your existing values and the unchanged chart version (see Manual Upgrade). Its keycloak-reconcile pre-upgrade hook reads the Secret and patches the matching Keycloak client to the new secret. The hook pod's log shows the change as client <id>: updated (secret).

Alternatively, set the new value by hand in the Keycloak admin console (boltmcp realm → Clients → the client → Credentials), then skip to step 3. The next helm upgrade finds the client already in sync.

3. Restart the consumers

Pods read the Secret only at startup. Restart the Deployment(s) listed in the table above for the key you rotated:

kubectl rollout restart -n ${NAMESPACE} deployment/${RELEASE}-web

Between steps 1 and 3 the running pods still hold the old value while Keycloak already expects the new one, so sign-ins and token refreshes for that client fail until the restart completes. Do steps 2 and 3 back to back.

Do the steps in this order. Restarting a pod before the Keycloak client is updated puts the new secret on the pod and the old one in Keycloak, which fails the same way. If a rotation has gone wrong, see Client Secret Mismatch.

Other Secrets

The boltmcp-database and boltmcp-auth Secrets are not covered here. Database passwords must also be changed in PostgreSQL (ALTER USER ... PASSWORD ...), and the Keycloak operator and first-user passwords are only read at Keycloak's first boot, so changing them in the Secret has no effect on an existing install. See Values-Only Changes for restarting the Deployments that consume a changed Secret.

On this page