Trust a custom CA for outbound connections on Kubernetes
For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append.mdto anykestra.io/docs/*URL for plain Markdown.
Add a self-signed or internal CA certificate to the JVM truststore so Kestra tasks can make outbound calls to services secured by that CA.
This is common in environments where internal services — such as databases, APIs, or artifact registries — use a private or self-signed certificate authority not included in the JVM’s default truststore. Without this configuration, tasks that connect to those services fail with:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: unable to find valid certification path to requested targetPrerequisites
You need kubectl, keytool (bundled with the JDK), and helm.
The commands use the following variables:
| Variable | Description |
|---|---|
$NAMESPACE | Kubernetes namespace where Kestra is running |
$WEBSERVER_POD_NAME | Name of a running Kestra pod (e.g., the webserver or executor) |
$ALIAS_FOR_YOUR_DOMAIN | Unique alias for your certificate (e.g., my-internal-ca) |
$RELEASE_NAME | Helm release name for your Kestra installation |
Steps
-
Prepare a working directory:
mkdir sslcp /path/to/self-signed-certificate.pem ./ssl/ -
Retrieve the base keystore from the running pod: Pull the default Java truststore (
cacerts) from a running pod to preserve all standard public CAs while you add your own.kubectl get po -n $NAMESPACEWEBSERVER_POD_NAME=<pod-name-from-above>kubectl cp $NAMESPACE/$WEBSERVER_POD_NAME:/opt/java/openjdk/lib/security/cacerts ./ssl/cacertsls -l ./ssl -
Import and convert the certificate: Import your PEM file into the downloaded truststore:
keytool -importcert \-trustcacerts \-file ssl/self-signed-certificate.pem \-keystore ssl/cacerts \-alias $ALIAS_FOR_YOUR_DOMAIN \-storepass changeit \-nopromptConvert the modified keystore to PKCS12 format:
keytool -importkeystore \-srckeystore ssl/cacerts \-destkeystore ssl/truststore.p12 \-deststoretype PKCS12 \-srcstorepass changeit \-deststorepass changeitVerify your alias is present in the new truststore:
keytool -list -keystore ssl/truststore.p12 -storetype PKCS12 -storepass changeit | grep $ALIAS_FOR_YOUR_DOMAINIf the command returns a line containing your alias, the import was successful.
-
Create a Kubernetes Secret:
kubectl create secret generic kestra-ssl \--from-file=truststore.p12=ssl/truststore.p12 \-n $NAMESPACEThe
--from-file=key=pathsyntax sets the key name inside the Secret totruststore.p12, so the mounted filename matches the JVM path configured in step 5. -
Configure Helm: Add the following to your
values.yamlto mount the secret and point the JVM to it:common:extraVolumeMounts:- name: ssl-secretmountPath: "/app/ssl"readOnly: trueextraVolumes:- name: ssl-secretsecret:secretName: kestra-sslextraEnv:- name: JAVA_OPTSvalue: >--Djavax.net.ssl.trustStore=/app/ssl/truststore.p12-Djavax.net.ssl.trustStorePassword=changeit-Djavax.net.ssl.trustStoreType=PKCS12Then apply the changes:
helm upgrade --install $RELEASE_NAME kestra/kestra -n $NAMESPACE -f /path/to/values.yaml
The default Java keystore password is changeit. If your organization uses a different password, update it consistently across all keytool and JAVA_OPTS references above.
Was this page helpful?