🆕 New to KubeDB? Start with the quickstart guide before continuing here.

Neo4j Auth Rotation with KubeDB

Auth rotation replaces the Neo4j admin password without downtime. KubeDB updates the Kubernetes Secret and rotates the credential inside the running cluster automatically through Neo4jOpsRequest.

This guide covers two rotation modes:

ModeWhen to use
KubeDB-generatedLet KubeDB create a new random password
User-providedSupply your own password via a Kubernetes Secret

How It Works

KubeDB uses Neo4jOpsRequest with type: RotateAuth to rotate credentials. Under the hood it:

  1. Generates a new password or reads one from spec.authentication.secretRef
  2. Updates the Kubernetes auth Secret
  3. Calls the Neo4j password-change API on the running cluster
  4. Marks the operation Successful once all pods accept the new credential

Prerequisites

RequirementDetails
KubeDB installedProvisioner and Ops-manager operators running
Neo4j instanceneo4j-test in namespace demo, status.phase=Ready
kubectl configuredWith permissions to the demo namespace

Step 2 — Deploy Neo4j

Save this as neo4j.yaml:

apiVersion: kubedb.com/v1alpha2
kind: Neo4j
metadata:
  name: neo4j-test
  namespace: demo
spec:
  version: "2025.10.1"
  replicas: 3
  storage:
    resources:
      requests:
        storage: 2Gi
    storageClassName: standard
    accessModes:
      - ReadWriteOnce
  deletionPolicy: WipeOut

Apply it and wait for the cluster to become ready:

kubectl apply -f neo4j.yaml

kubectl get neo4j -n demo neo4j-test -w

Wait until STATUS shows Ready before proceeding.

NAME         VERSION     STATUS   AGE
neo4j-test   2025.10.1   Ready    3m

Mode 1 — KubeDB-Generated Password

In this mode, KubeDB generates a new random password and stores it back in the auth Secret.

Step 1 — Record the Current Password Hash

Capture the current base64-encoded password so you can confirm it changes after rotation.

BEFORE_B64=$(kubectl get secret -n demo neo4j-test-auth -o jsonpath='{.data.password}')
echo "Before: $BEFORE_B64"

Step 2 — Apply the RotateAuth Request

Save this as neo4j-rotate-auth.yaml:

apiVersion: ops.kubedb.com/v1alpha1
kind: Neo4jOpsRequest
metadata:
  name: neo4j-rotate-auth
  namespace: demo
spec:
  type: RotateAuth
  databaseRef:
    name: neo4j-test
  timeout: 5m
  apply: IfReady

Apply it and wait for completion:

$ kubectl apply -f neo4j-rotate-auth.yaml

$ kubectl wait --for=jsonpath='{.status.phase}'=Successful \
  neo4jopsrequest/neo4j-rotate-auth \
  -n demo --timeout=900s

Expected output:

neo4jopsrequest.ops.kubedb.com/neo4j-rotate-auth condition met

Step 3 — Verify the Password Changed

$ kubectl get neo4jopsrequest -n demo neo4j-rotate-auth

AFTER_B64=$(kubectl get secret -n demo neo4j-test-auth -o jsonpath='{.data.password}')
[ "$BEFORE_B64" != "$AFTER_B64" ] && echo "password_changed=true" || echo "password_changed=false"

NEW_PASS=$(kubectl get secret -n demo neo4j-test-auth -o jsonpath='{.data.password}' | base64 -d)
$ kubectl exec -n demo neo4j-test-0 -- cypher-shell -u neo4j -p "$NEW_PASS" "RETURN 'auth-ok' AS status"

Expected output:

NAME                TYPE         STATUS       AGE
neo4j-rotate-auth   RotateAuth   Successful   37s

password_changed=true

status
"auth-ok"

✅ The password in the Secret has changed and Neo4j accepts the new credential.


Mode 2 — User-Provided Password

In this mode, you supply a Kubernetes Secret containing your chosen password. KubeDB reads it and rotates Neo4j to use it.

Step 1 — Create the Auth Secret

$ kubectl create secret generic external-neo4j-auth \
  -n demo \
  --from-literal=username=neo4j \
  --from-literal=password='Neo4j@12345' \
  --dry-run=client -o yaml | kubectl apply -f -

Password requirements: Neo4j requires the password to differ from the username and be at least 8 characters.

Step 2 — Apply the RotateAuth Request

Save this as neo4j-rotate-auth-user.yaml:

apiVersion: ops.kubedb.com/v1alpha1
kind: Neo4jOpsRequest
metadata:
  name: neo4j-rotate-auth-user
  namespace: demo
spec:
  type: RotateAuth
  databaseRef:
    name: neo4j-test
  authentication:
    secretRef:
      kind: Secret
      name: external-neo4j-auth
  timeout: 5m
  apply: IfReady

Apply it and wait for completion:

$ kubectl apply -f neo4j-rotate-auth-user.yaml

$ kubectl wait --for=jsonpath='{.status.phase}'=Successful \
  neo4jopsrequest/neo4j-rotate-auth-user \
  -n demo --timeout=900s

Expected output:

neo4jopsrequest.ops.kubedb.com/neo4j-rotate-auth-user condition met

Step 3 — Verify Login with the New Password

$ kubectl get neo4jopsrequest -n demo neo4j-rotate-auth-user

$ kubectl exec -n demo neo4j-test-0 -- \
  cypher-shell -u neo4j -p 'Neo4j@12345' "RETURN 'user-auth-ok' AS status"

Expected output:

NAME                     TYPE         STATUS       AGE
neo4j-rotate-auth-user   RotateAuth   Successful   33s

status
"user-auth-ok"

✅ Neo4j now accepts the password from external-neo4j-auth.


Understanding the OpsRequest Fields

FieldDescription
spec.typeRotateAuth — identifies this as a credential rotation operation
spec.databaseRef.nameName of the target Neo4j resource
spec.authentication.secretRef(Optional) Secret with username and password keys. Omit to let KubeDB generate a password.
spec.timeoutHow long KubeDB waits before marking the operation failed
spec.applyIfReady — only proceed if the database is in a healthy state

Cleanup

kubectl delete neo4jopsrequest -n demo neo4j-rotate-auth neo4j-rotate-auth-user
kubectl delete secret -n demo external-neo4j-auth
kubectl delete neo4j -n demo neo4j-test
kubectl delete ns demo

Next Steps