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.6.19/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