Meili CDC Docs

Kubernetes

Run meilisearch-cdc as a single-replica Deployment with a persistent volume for its embedded state store, and pass secrets as files.

Exactly one replica

All state (tasks, checkpoints, users) lives in one embedded database file that a single process locks. Do not scale the Deployment above one replica, and use the Recreate strategy so the old pod releases the volume before the new one starts. For more throughput, raise the per-task batching settings or run separate installations with separate data directories.

Secrets

Generate an encryption key once and keep it outside the cluster as well: without it, stored credentials cannot be decrypted.

kubectl create namespace cdc
kubectl -n cdc create secret generic meilisearch-cdc \
  --from-literal=secret-key="$(openssl rand -base64 32)" \
  --from-literal=admin-token="$(openssl rand -hex 32)" \
  --from-literal=admin-password='choose-a-strong-password'

A base64 string that decodes to exactly 32 bytes is used as the AES-256 key directly; any other value is treated as a passphrase and stretched with argon2id.

Manifests

apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: meilisearch-cdc-data, namespace: cdc}
spec:
  accessModes: [ReadWriteOnce]
  resources: {requests: {storage: 2Gi}}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: meilisearch-cdc, namespace: cdc}
spec:
  replicas: 1                      # never more: the state store is single-writer
  strategy: {type: Recreate}
  selector: {matchLabels: {app: meilisearch-cdc}}
  template:
    metadata: {labels: {app: meilisearch-cdc}}
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        runAsGroup: 65532
        fsGroup: 65532
      terminationGracePeriodSeconds: 45   # CDC_STOP_TIMEOUT (20s) + 10s + margin
      containers:
        - name: cdc
          image: ghcr.io/ja7ad/meilisearch-cdc:1.2.3
          ports: [{name: http, containerPort: 8080}]
          env:
            - {name: CDC_DATA_DIR, value: /data}
            - {name: CDC_LOG_FORMAT, value: json}
            - {name: CDC_PUBLIC_URL, value: https://cdc.example.com}
            - {name: CDC_TRUST_PROXY, value: "true"}
            - {name: CDC_COOKIE_SECURE, value: "true"}
            - {name: CDC_ADMIN_EMAIL, value: admin@example.com}
            - {name: CDC_SECRET_KEY_FILE, value: /run/secrets/cdc/secret-key}
            - {name: CDC_ADMIN_TOKEN_FILE, value: /run/secrets/cdc/admin-token}
            - {name: CDC_ADMIN_PASSWORD_FILE, value: /run/secrets/cdc/admin-password}
            - {name: GOMEMLIMIT, value: 400MiB}
          volumeMounts:
            - {name: data, mountPath: /data}
            - {name: secrets, mountPath: /run/secrets/cdc, readOnly: true}
          resources:
            requests: {cpu: 100m, memory: 128Mi}
            limits: {memory: 512Mi}
          livenessProbe:
            httpGet: {path: /healthz, port: http}
            periodSeconds: 10
          readinessProbe:
            httpGet: {path: /healthz, port: http}
            periodSeconds: 5
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities: {drop: [ALL]}
      volumes:
        - name: data
          persistentVolumeClaim: {claimName: meilisearch-cdc-data}
        - name: secrets
          secret: {secretName: meilisearch-cdc, defaultMode: 0400}
---
apiVersion: v1
kind: Service
metadata: {name: meilisearch-cdc, namespace: cdc}
spec:
  selector: {app: meilisearch-cdc}
  ports: [{name: http, port: 80, targetPort: http}]

Notes

  • Probes. /healthz needs no authentication and answers ok while the HTTP server runs. Do not use /api/v1/health as a liveness probe: it also checks Meilisearch, and a Meilisearch outage should not restart this pod.
  • Admin account. CDC_ADMIN_EMAIL with CDC_ADMIN_PASSWORD_FILE creates the first admin on start when no user exists; afterwards they are ignored.
  • Metrics. /metrics requires authentication. Give Prometheus the admin token as a bearer token; see Prometheus.
  • Admin CLI. kubectl -n cdc exec -it deploy/meilisearch-cdc -- meilisearch-cdc admin users list talks to the running service over its socket in /data.
  • Declarative tasks. Mount a ConfigMap with a tasks file and set CDC_TASKS_FILE; credentials come from environment variables expanded with ${VAR}. See Declarative tasks file.
  • Server-Sent Events. If an Ingress controller buffers responses, the dashboard's live updates stall. For ingress-nginx, set the annotations nginx.ingress.kubernetes.io/proxy-buffering: "off" and a long proxy-read-timeout. See Reverse proxy and TLS.

Backups

Snapshot the volume while the pod is scaled to zero, or copy /data/cdc.db as described in Backups and upgrades. The key lives in the Secret, so back that up too.

Meili CDC user guide · last updated 2026-10-26 · Edit this page on GitHub

meilisearch-cdc is open source. Meilisearch is a trademark of Meili SAS; this project is not affiliated with it.