TLS certificate troubleshooting
This guide covers common TLS certificate errors in MinIO AIStor deployments and provides procedures for diagnosing and resolving them.
For general TLS setup, see the platform-specific network encryption guides under Installation. For cert-manager integration, see TLS certificate management with cert-manager.
Common error messages
Certificate signed by unknown authority
x509: certificate signed by unknown authority
The server presented a certificate signed by a CA that the client does not trust.
Causes:
- The CA certificate is not in the client’s trust store
- The server certificate was signed by an intermediate CA, and the intermediate is missing from the chain
- On Kubernetes, the operator webhook certificate is signed by a different CA than what the MinIO pods trust
Resolution:
-
Identify the certificate’s issuer:
openssl s_client -connect HOSTNAME:PORT -showcerts </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject -
Verify the CA is present in the MinIO trust store.
For Linux deployments, place the CA certificate in the MinIO certs directory:
cp ca.crt ~/.minio/certs/CAs/For Kubernetes deployments, verify the CA is mounted in the pod:
kubectl exec -n NAMESPACE POD -c minio -- ls -la /tmp/minio/certs/CAs/ -
Verify the mounted CA matches the expected CA:
kubectl exec -n NAMESPACE POD -c minio -- openssl x509 -in /tmp/minio/certs/CAs/ca-0.crt -noout -subject -issuerIf the mounted certificate does not match the CA in the Kubernetes secret, the operator mount secret may be stale. See Stale mount secret below.
Certificate has expired
x509: certificate has expired or is not yet valid
The server or CA certificate has passed its expiry date, or the system clock is incorrect.
Resolution:
-
Check the certificate expiry date:
openssl s_client -connect HOSTNAME:PORT </dev/null 2>/dev/null | openssl x509 -noout -dates -
Verify system clocks are synchronized across all nodes. MinIO AIStor requires clocks to be within 15 minutes of each other.
-
Renew the certificate. For cert-manager managed certificates, check the Certificate resource status:
kubectl get certificate -n NAMESPACE -o wide -
Monitor certificate expiry proactively using the Prometheus metric:
minio_system_network_certificate_expires_in
Certificate name mismatch
x509: certificate is valid for X, not Y
The hostname used to connect does not match any Subject Alternative Name (SAN) in the certificate.
Resolution:
-
Inspect the certificate’s SANs:
openssl s_client -connect HOSTNAME:PORT </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName -
Verify the hostname matches one of the listed SANs.
-
If using a load balancer or proxy, verify the certificate covers both the external hostname and the internal service names.
TLS handshake failure
tls: bad certificate
or
remote error: tls: bad certificate
The TLS handshake failed because the client rejected the server’s certificate, or the server rejected the client’s certificate in an mTLS configuration.
Resolution:
-
Test connectivity with verbose TLS output:
curl -v https://HOSTNAME:PORT 2>&1 | grep -A5 "SSL certificate" -
For Kubernetes deployments, test from inside a MinIO pod to verify what the pod sees:
kubectl exec -n NAMESPACE POD -c minio -- curl -v --cacert /tmp/minio/certs/CAs/ca-0.crt https://TARGET:PORT -
If the test succeeds with
--cacertbut fails without it, the CA is not in the system or MinIO trust store.
Kubernetes-specific issues
Stale mount secret
The MinIO operator assembles all referenced certificates into a single mount secret named <objectstore-name>-generated in the tenant namespace.
If the underlying certificate secrets are updated but the mount secret is not refreshed, the pods continue using outdated certificates.
Symptoms:
- The CA in the Kubernetes secret is correct, but the CA mounted in the pod is a different (older) certificate
- TLS errors persist after updating certificate secrets
Resolution:
-
Delete the mount secret to force the operator to rebuild it:
kubectl delete secret OBJECTSTORE_NAME-generated -n NAMESPACE -
The operator recreates the mount secret from the current certificate secrets and restarts the affected pods.
-
Verify the correct certificate is now mounted:
kubectl exec -n NAMESPACE POD -c minio -- openssl x509 -in /tmp/minio/certs/CAs/ca-0.crt -noout -subject -issuer
Operator webhook certificate trust
The MinIO AIStor operator serves an upgrade webhook on port 4221.
By default, the operator generates its own TLS certificate using the Kubernetes CSR API with the kubernetes.io/kubelet-serving signer.
This certificate is signed by the cluster’s kubelet CA (CN=ca-kubelet), which MinIO pods may not trust.
Symptoms:
- MinIO version updates fail with
x509: certificate signed by unknown authoritywhen connecting to the operator webhook - The operator log shows
TLS handshake error from <IP>: remote error: tls: bad certificate
Resolution:
Disable operator autocert and provide a certificate signed by the same CA that the MinIO pods trust:
-
Create a cert-manager Certificate for the operator webhook:
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: operator-webhook-tls namespace: OPERATOR_NAMESPACE spec: secretName: object-store-operator-tls issuerRef: name: YOUR_ISSUER kind: ClusterIssuer dnsNames: - object-store-operator - object-store-operator.OPERATOR_NAMESPACE.svc - object-store-operator.OPERATOR_NAMESPACE.svc.cluster.local duration: 8760h renewBefore: 720h -
Set the following environment variables on the operator deployment:
env: - name: OPERATOR_AUTO_CERT_DISABLED value: "on" - name: OPERATOR_CUSTOM_TLS_SECRET_NAME value: "object-store-operator-tls"
Verification commands
Use the following commands to diagnose TLS issues.
Inspect a remote certificate
openssl s_client -connect HOSTNAME:PORT -showcerts </dev/null 2>/dev/null | openssl x509 -noout -text
Check certificate expiry
openssl s_client -connect HOSTNAME:PORT </dev/null 2>/dev/null | openssl x509 -noout -enddate
Verify a certificate against a CA
openssl verify -CAfile ca.crt server.crt
Test TLS from inside a Kubernetes pod
kubectl exec -n NAMESPACE POD -c minio -- openssl s_client -connect TARGET:PORT -CAfile /tmp/minio/certs/CAs/ca-0.crt </dev/null
List all certificates mounted in a MinIO pod
kubectl exec -n NAMESPACE POD -c minio -- find /tmp/minio/certs -name "*.crt" -exec openssl x509 -in {} -noout -subject -issuer -enddate \;
Check MinIO certificate expiry via Prometheus
Query the minio_system_network_certificate_expires_in metric to find certificates approaching expiry:
minio_system_network_certificate_expires_in < 604800
This returns certificates expiring within 7 days (604800 seconds).
Related pages
- Enable TLS encryption for certificate file placement on Linux
- TLS certificate management with cert-manager for automated certificate provisioning
- System tuning checklist for NTP and time synchronization requirements