You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Keystores and truststores from SECRET_VOLUME (/var/secrets/opendj by default) are copied into ./data/config only on the first start, when the instance is bootstrapped (run.sh#L80-L88). When ./data/config already exists, the script execs the server before reaching that step (L44-L53).
So a renewed certificate in the mounted Secret never reaches a server with a persistent volume. A restart keeps serving the old one until it expires. On Kubernetes, where cert-manager renews the Secret regularly, this means TLS fails once the first certificate expires.
The volume is also hard to use from Kubernetes: only JKS/PKCS12 files named key* / trust* are picked up. A kubernetes.io/tls Secret (cert-manager) holds PEM files (tls.crt, tls.key, ca.crt), which OpenDJ 4.x cannot use directly (it has no PEM key manager).
Expected
Every start refreshes the keystore/truststore from SECRET_VOLUME, before the server starts, when the volume is present.
Optionally, a tls.crt/tls.key/ca.crt set is converted to PKCS12 at that point, so a cert-manager Secret can be mounted as is. The keystore PIN comes from a file, never from the log.
Notes
Needed for the TLS part of the Helm chart proposal (discussion #1079).
Analysis (2026-09-24)
Measured with openidentityplatform/opendj:latest (5.1.2, JDK 25), a JKS keystore + keystore.pin mounted at /var/secrets/opendj and a named data volume:
CN=secret-v1 (the keystore on the volume is still v1)
The first start does not serve the mounted certificate either. The copy (run.sh#L80-L88) runs after setup.sh, which has already started the server. By then the LDAPS connection handler has built its SSLContext from the self-signed keystore, and the script goes on to tail -f (#1085). The mounted certificate is served only after the first restart.
Copying on every start is not enough on Kubernetes. cert-manager renews the Secret, and nothing restarts the pod. A connection handler builds its SSLContext once, when it is initialized or its own configuration changes (LDAPConnectionHandler#configureSSL). After cp of a new keystore into config/, LDAPS keeps the old certificate. Any dsconfig set-connection-handler-prop on the handler makes it serve the new one at once, so reloading works without a restart, but only with admin credentials. The server side is #1095.
Not a problem, checked:
The LDAPS handler has no ssl-cert-nickname (only the administration connector, admin-cert, and replication, ads-certificate, have one), so a keystore whose key is under any alias works, e.g. certificate as cert-manager names it.
The cn=JKS provider reads a PKCS12 file named keystore.
The key* / trust* globs do not match admin-keystore, admin-truststore or ads-truststore. The volume affects LDAPS and StartTLS only.
On the optional PEM part: openssl is in the Ubuntu based image but not in the Alpine one, and keytool cannot import a PEM private key. cert-manager can add a PKCS12 keystore to the Secret it issues (spec.keystores.pkcs12, password from passwordSecretRef), and a projected volume can mount it as keystore, with the password as keystore.pin. That needs no conversion in the image.
Problem
Keystores and truststores from
SECRET_VOLUME(/var/secrets/opendjby default) are copied into./data/configonly on the first start, when the instance is bootstrapped (run.sh#L80-L88). When./data/configalready exists, the scriptexecs the server before reaching that step (L44-L53).So a renewed certificate in the mounted Secret never reaches a server with a persistent volume. A restart keeps serving the old one until it expires. On Kubernetes, where cert-manager renews the Secret regularly, this means TLS fails once the first certificate expires.
The volume is also hard to use from Kubernetes: only JKS/PKCS12 files named
key*/trust*are picked up. Akubernetes.io/tlsSecret (cert-manager) holds PEM files (tls.crt,tls.key,ca.crt), which OpenDJ 4.x cannot use directly (it has no PEM key manager).Expected
SECRET_VOLUME, before the server starts, when the volume is present.tls.crt/tls.key/ca.crtset is converted to PKCS12 at that point, so a cert-manager Secret can be mounted as is. The keystore PIN comes from a file, never from the log.Notes
Needed for the TLS part of the Helm chart proposal (discussion #1079).
Analysis (2026-09-24)
Measured with
openidentityplatform/opendj:latest(5.1.2, JDK 25), a JKSkeystore+keystore.pinmounted at/var/secrets/opendjand a named data volume:CN=localhost, O=OpenDJ RSA Self-Signed CertificateCN=secret-v1CN=secret-v1(the keystore on the volume is still v1)The first start does not serve the mounted certificate either. The copy (run.sh#L80-L88) runs after
setup.sh, which has already started the server. By then the LDAPS connection handler has built itsSSLContextfrom the self-signed keystore, and the script goes on totail -f(#1085). The mounted certificate is served only after the first restart.Copying on every start is not enough on Kubernetes. cert-manager renews the Secret, and nothing restarts the pod. A connection handler builds its
SSLContextonce, when it is initialized or its own configuration changes (LDAPConnectionHandler#configureSSL). Aftercpof a new keystore intoconfig/, LDAPS keeps the old certificate. Anydsconfig set-connection-handler-propon the handler makes it serve the new one at once, so reloading works without a restart, but only with admin credentials. The server side is #1095.Not a problem, checked:
ssl-cert-nickname(only the administration connector,admin-cert, and replication,ads-certificate, have one), so a keystore whose key is under any alias works, e.g.certificateas cert-manager names it.cn=JKSprovider reads a PKCS12 file namedkeystore.key*/trust*globs do not matchadmin-keystore,admin-truststoreorads-truststore. The volume affects LDAPS and StartTLS only.On the optional PEM part:
opensslis in the Ubuntu based image but not in the Alpine one, and keytool cannot import a PEM private key. cert-manager can add a PKCS12 keystore to the Secret it issues (spec.keystores.pkcs12, password frompasswordSecretRef), and a projected volume can mount it askeystore, with the password askeystore.pin. That needs no conversion in the image.Fix:
exec start-dslike every later start (this is also the fix for Docker image: a freshly bootstrapped container ignores SIGTERM and is killed without stopping the server #1085); keep checking the volume while the server runs and copy changed files by rename; document the cert-manager setup.