Overview
Qdrant is an open-source (Apache-2.0) vector database for similarity search and retrieval-augmented generation. This template deploys a single Qdrant 1.18 server with persistent storage, REST and gRPC APIs, optional API-key authentication, and scheduled platform volume snapshots. There is no feature gating — everything in the upstream open-source build is available.What Gets Created
Prerequisites
None for a default install. Qdrant needs no database, cache, or object store, and backups use platform volume snapshots rather than a cloud account or bucket. Authentication is optional but strongly recommended, and it is required before you can enable public access. It is driven by a dictionary secret you create yourself and reference by name:Create the API-key secret
api-key entry. The read-only-api-key entry is only needed when you set auth.readOnlyKey: true.api-key— the primary key; full read and write access.read-only-api-key— can search, scroll, and read collections; writes are rejected.
auth.secretName to this name.Installation
A default install needs no--set values. To enable authentication, add --set auth.secretName=SECRET_NAME (the secret must already exist).
UI
CLI
Terraform
Pulumi
Configuration
Image
Resources
on_disk vectors or index, so raise maxMemory before loading a large collection.
Storage
/qdrant/data holds both storage/ (collections, segments, HNSW indexes, WAL) and snapshots/ (Qdrant’s own collection snapshots), so snapshots you create through the API survive restarts and redeployments.
Backup
backup.retention, regardless of backup.enabled — setting it to false disables scheduled snapshots only. They are independent of Qdrant’s own collection snapshots, which you create through the API (see Backing Up).
Authentication
api-key header. The read-only key can search, scroll, and read collections; write operations are rejected with 403 Forbidden: Global manage access is required. Qdrant’s health paths (/healthz, /livez, /readyz) stay reachable without a key; /metrics is not exempt and returns 401 without one.
Service
service.dashboard: false on any publicly exposed instance.
Access
publicAccess.enabled: true requires auth.secretName; the chart refuses to render without it. gRPC always stays internal.
Connecting
Python Client
Using Qdrant with Other Templates
Qdrant is the retrieval tier of a RAG stack, and every other component reaches it over internal GVC DNS with no public exposure. Deploy them into the same GVC and wire them by hostname. Each address below uses that template’s own release name:VECTOR_DB=qdrant, QDRANT_URI=http://RELEASE_NAME-qdrant.GVC_NAME.cpln.local:6333, and QDRANT_API_KEY. The open-webui template does not expose these as values yet — set them on the deployed workload.
Operations
Backing Up
Two different things are called “snapshots”, and they complement each other: Platform volume snapshots (backup.*) are block-level snapshots of the whole data volume, taken on backup.schedule and on delete. List them, or take one on demand:
/qdrant/data/snapshots/COLLECTION_NAME/ on the data volume, so they survive restarts and are included in platform volume snapshots. Keep a downloaded copy of anything you cannot afford to lose — an uninstall deletes the volume.
Qdrant can also take a full-storage snapshot (POST /snapshots), but upstream restores it only through a startup flag that this template does not expose. Use collection snapshots instead.
Restoring a Backup
.snapshot file to the server (a fresh install works, as long as it runs the same or the next minor version of Qdrant). priority=snapshot makes the snapshot data win over whatever the target collection currently holds; without it, recovering into an empty collection leaves it empty. With a port-forward open:
restoreVolume command on the volume set — see the volume set reference. The equivalent CLI form, which has not been exercised on this template, is:
Rotating the API Key
The running replica readscpln://secret/... references once, at start. After you change the api-key (or read-only-api-key) entry in your dictionary secret, the old key keeps working until the workload restarts — force a redeployment to apply the new one:
Scaling and Availability
- Single replica by design. There is no
replicasknob: the volume set is per-replica, so a second replica would serve a separate, empty store, and Qdrant’s distributed mode is not part of this version. - Upgrades and reschedules are a real outage. Any
helm upgrade, configuration change, or reschedule takes the API fully offline until the replacement replica is ready. Plan writes around it. Data, collections, and Qdrant snapshots on the volume survive. - Scale vertically. Raise
resources.maxMemorybefore loading a large collection, or have the client create collections withon_diskvectors and index. Changing resources is ahelm upgrade, with the outage above.
Troubleshooting
Install fails: publicAccess.enabled requires auth.secretName
Install fails: publicAccess.enabled requires auth.secretName
cpln helm install fails at render time with qdrant: publicAccess.enabled requires auth.secretName — never expose Qdrant publicly without an API key.Cause: The chart refuses to expose an unauthenticated vector database to the internet.Fix: Create the dictionary secret described in Prerequisites and set auth.secretName to its name, or leave publicAccess.enabled: false.Install fails: auth.readOnlyKey requires auth.secretName
Install fails: auth.readOnlyKey requires auth.secretName
qdrant: auth.readOnlyKey requires auth.secretName.Cause: The read-only key is read from the same secret as the primary key, so it cannot be enabled on its own.Fix: Set auth.secretName, and make sure the secret has a read-only-api-key entry.Install fails: volumeset.capacity must be at least 10
Install fails: volumeset.capacity must be at least 10
qdrant: volumeset.capacity must be at least 10 (GiB, platform minimum).Fix: Set volumeset.capacity to 10 or more.Deployment never becomes ready after setting auth.secretName
Deployment never becomes ready after setting auth.secretName
cpln logs returns no lines at all.Cause: The secret named in auth.secretName does not exist, or its api-key (or read-only-api-key) entry is missing. Check status.versions[].message in cpln workload get-deployments RELEASE_NAME-qdrant --gvc GVC_NAME -o yaml — it names the missing secret.Fix: Create the secret with the exact entry names, then wait a few minutes or run cpln workload force-redeployment RELEASE_NAME-qdrant --gvc GVC_NAME.Python client hangs with gRPC DEADLINE_EXCEEDED
Python client hangs with gRPC DEADLINE_EXCEEDED
qdrant-client call from inside the GVC never returns, then fails with DEADLINE_EXCEEDED.Cause: The client enabled TLS automatically because api_key was set, but the internal endpoint speaks plain HTTP and gRPC.Fix: Pass https=False to QdrantClient, or use explicit http:// URLs.403 Forbidden: Global manage access is required
403 Forbidden: Global manage access is required
403 Forbidden: Global manage access is required.Cause: The request used the read-only-api-key.Fix: Use the primary api-key for write operations.HTTP 400: JSON payload is larger than allowed
HTTP 400: JSON payload is larger than allowed
JSON payload (N bytes) is larger than allowed (limit: M bytes). and no points are written.Cause: The request body exceeded service.maxRequestSizeMb (32 MB by default).Fix: Send smaller batches, or raise service.maxRequestSizeMb and run helm upgrade.401 from /metrics with authentication enabled
401 from /metrics with authentication enabled
/healthz, /livez, and /readyz answer without a key, but /metrics returns 401.Cause: Only the health paths are exempt from the API key.Fix: Send the api-key header when scraping /metrics.403 RBAC: access denied from the canonical endpoint
403 RBAC: access denied from the canonical endpoint
*.cpln.app hostname are refused with RBAC: access denied.Cause: publicAccess.enabled is false, or it was just switched on and the change has not finished propagating.Fix: Set publicAccess.enabled: true together with auth.secretName, run helm upgrade, and allow a few minutes before retrying.Container restarts while loading a large collection
Container restarts while loading a large collection
cpln workload get-deployments RELEASE_NAME-qdrant --gvc GVC_NAME -o yaml shows restarts with reason OOMKilled; nothing is logged by Qdrant itself.Cause: The HNSW index outgrew resources.maxMemory.Fix: Raise resources.maxMemory, or create the collection with vectors.on_disk: true and hnsw_config.on_disk: true — a per-collection client choice, not a template knob.Important Notes
- Public access requires an API key. Installing with
publicAccess.enabled: trueand an emptyauth.secretNamefails at render time — create the dictionary secret first. - In-GVC clients must disable TLS.
qdrant-clientturns TLS on automatically when anapi_keyis set; passhttps=Falseor use plainhttp://URLs. - The
/dashboardshell loads without an API key (its API calls do not). Setservice.dashboard: falsewhen Qdrant is publicly exposed. - Single replica by design. Every upgrade or reschedule takes the API fully offline until the new replica is ready; plan writes around it. There is no
replicasknob. - Rotating the API key needs a redeployment. The new value is not picked up until you run
cpln workload force-redeployment RELEASE_NAME-qdrant --gvc GVC_NAME. - Over-size requests return HTTP 400, not 413, and write nothing. Batch large upserts or raise
service.maxRequestSizeMb. - Two kinds of snapshots.
backup.*controls platform volume snapshots; Qdrant’s collection snapshots are created through the API and live on the same volume. - Uninstall deletes the volume set. A final snapshot is retained for
backup.retention, a reinstall starts empty, and your own API-key secret is left untouched. - Memory is the sizing constraint. Vectors and HNSW graphs stay in RAM unless a collection is created with
on_diskvectors or index. Raiseresources.maxMemorybefore loading large collections.