You are looking at the documentation of a prior release. To read the documentation of the latest release, please visit here.

New to KubeDB? Please start here.

Configure TLS for Weaviate

This tutorial will show you how to provision a Weaviate cluster with TLS enabled from the start, using KubeDB and cert-manager.

Before You Begin

  • At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster.

  • Install KubeDB in your cluster following the steps here.

  • Install cert-manager in your cluster — Weaviate TLS is issued through cert-manager.

  • You should be familiar with the following KubeDB concepts:

To keep things isolated, this tutorial uses a separate namespace called demo throughout this tutorial.

$ kubectl create ns demo
namespace/demo created

Note: YAML files used in this tutorial are stored in docs/examples/weaviate/tls folder in GitHub repository kubedb/docs.

Create an Issuer

Weaviate TLS is issued through cert-manager. First, create a self-signed CA and a Secret that holds it:

$ openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
    -keyout weaviate-ca.key -out weaviate-ca.crt -subj "/CN=weaviate-ca"

$ kubectl create secret tls weaviate-ca \
    --cert=weaviate-ca.crt --key=weaviate-ca.key -n demo
secret/weaviate-ca created

Now, create an Issuer named weaviate-issuer that references this CA secret:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: weaviate-issuer
  namespace: demo
spec:
  ca:
    secretName: weaviate-ca
$ kubectl apply -f issuer.yaml
issuer.cert-manager.io/weaviate-issuer created

$ kubectl get issuer -n demo
NAME              READY   AGE
weaviate-issuer   True    3s

Deploy Weaviate with TLS

Now, create a Weaviate CR with spec.tls referencing the issuer. Setting clientAuth: true requires clients to present a valid client certificate (mutual TLS):

apiVersion: kubedb.com/v1alpha2
kind: Weaviate
metadata:
  name: weaviate-sample
  namespace: demo
spec:
  version: 1.33.1
  replicas: 3
  storageType: Durable
  storage:
    storageClassName: longhorn
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 1Gi
  tls:
    issuerRef:
      apiGroup: cert-manager.io
      kind: Issuer
      name: weaviate-issuer
    clientAuth: true
  deletionPolicy: WipeOut
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.7.10/docs/examples/weaviate/tls/tls.yaml
weaviate.kubedb.com/weaviate-sample created

Wait until the cluster becomes Ready:

$ kubectl get weaviate -n demo
NAME              TYPE                  VERSION   STATUS   AGE
weaviate-sample   kubedb.com/v1alpha2   1.33.1    Ready    73s

$ kubectl get pods -n demo -l app.kubernetes.io/instance=weaviate-sample
NAME                READY   STATUS    RESTARTS   AGE
weaviate-sample-0   1/1     Running   0          71s
weaviate-sample-1   1/1     Running   0          59s
weaviate-sample-2   1/1     Running   0          45s

Verify TLS Resources

KubeDB created cert-manager Certificate resources and the corresponding TLS secrets (a server and a client certificate):

$ kubectl get certificate -n demo
NAME                          READY   SECRET                        AGE
weaviate-sample-client-cert   True    weaviate-sample-client-cert   73s
weaviate-sample-server-cert   True    weaviate-sample-server-cert   73s

$ kubectl get secret -n demo | grep weaviate-sample
weaviate-sample-auth          Opaque              3      73s
weaviate-sample-client-cert   kubernetes.io/tls   4      73s
weaviate-sample-d25c86        Opaque              1      73s
weaviate-sample-server-cert   kubernetes.io/tls   3      73s

The spec.tls block on the Weaviate object reflects the TLS configuration:

$ kubectl get weaviate -n demo weaviate-sample -o jsonpath='{.spec.tls}' | jq
{
  "certificates": [
    {"alias": "server", "secretName": "weaviate-sample-server-cert"},
    {"alias": "client", "secretName": "weaviate-sample-client-cert"}
  ],
  "clientAuth": true,
  "issuerRef": {
    "apiGroup": "cert-manager.io",
    "kind": "Issuer",
    "name": "weaviate-issuer"
  }
}

With TLS enabled, the REST service is served over HTTPS on port 8443 instead of plain HTTP on 8080:

$ kubectl get svc -n demo weaviate-sample -o jsonpath='{range .spec.ports[*]}{.name}={.port} {end}'
https=8443 grpc=50051 gossip=7102 data=7103 raft=8300

You can inspect the issued server certificate:

$ kubectl get secret -n demo weaviate-sample-server-cert -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -subject -issuer -dates
subject=CN=weaviate-sample
issuer=CN=weaviate-ca
notBefore=Jun 30 18:07:40 2026 GMT
notAfter=Sep 28 18:07:40 2026 GMT

Connect over TLS

Because clientAuth is enabled, clients must present the client certificate. Extract the certificates from the client secret and connect through a port-forward:

$ kubectl get secret -n demo weaviate-sample-client-cert -o jsonpath='{.data.ca\.crt}'  | base64 -d > ca.crt
$ kubectl get secret -n demo weaviate-sample-client-cert -o jsonpath='{.data.tls\.crt}' | base64 -d > client.crt
$ kubectl get secret -n demo weaviate-sample-client-cert -o jsonpath='{.data.tls\.key}' | base64 -d > client.key

$ export WEAVIATE_API_KEY=$(kubectl get secret -n demo weaviate-sample-auth -o jsonpath='{.data.AUTHENTICATION_APIKEY_ALLOWED_KEYS}' | base64 -d)

$ kubectl port-forward -n demo svc/weaviate-sample 8443:8443
# in another terminal
$ curl -s -o /dev/null -w "%{http_code}\n" \
    --cacert ca.crt --cert client.crt --key client.key \
    https://localhost:8443/v1/.well-known/ready \
    -H "Authorization: Bearer $WEAVIATE_API_KEY"
200

$ curl -s --cacert ca.crt --cert client.crt --key client.key \
    https://localhost:8443/v1/nodes \
    -H "Authorization: Bearer $WEAVIATE_API_KEY" | jq '.nodes[] | {name, status}'
{"name": "weaviate-sample-0", "status": "HEALTHY"}
{"name": "weaviate-sample-1", "status": "HEALTHY"}
{"name": "weaviate-sample-2", "status": "HEALTHY"}

All three nodes are reachable over the TLS-encrypted, mutually-authenticated REST endpoint.

Next Steps

Cleaning up

To clean up the Kubernetes resources created by this tutorial, run:

$ kubectl delete weaviate -n demo weaviate-sample
$ kubectl delete issuer -n demo weaviate-issuer
$ kubectl delete secret -n demo weaviate-ca
$ kubectl delete ns demo