Qdrant - Hardened Vector Database
par Lynxroute
Qdrant 1.18.2 - CIS Level 1 hardened vector database on Ubuntu 24.04 LTS with SBOM and CIS Report
What is Qdrant
Qdrant is an open-source, high-performance vector database and similarity search engine written in Rust. It indexes high-dimensional embeddings using HNSW and serves nearest-neighbor queries in milliseconds with rich payload filtering. Qdrant is the storage and retrieval layer for retrieval-augmented generation (RAG), semantic search, recommendation engines, and any workload where exact keyword search is not enough. It exposes a REST API on port 6333, a gRPC API on port 6334, and a built-in Web UI for collection management.
Why self-host Qdrant
Self-hosting keeps your embeddings, payload data, and query traffic inside your own tenant - no per-vector SaaS fees, no third-party access to what your users are searching for, no data leaving your region. Ideal for teams with data residency requirements (GDPR, HIPAA, ISO 27001), organisations running on-premise RAG pipelines over confidential corpora, and ML platforms that need predictable latency without round-trips to a managed service.
What this VM image adds
Security hardening:
- Unique API key generated per instance - 64-character random key written at first boot, never the same on two deployments; stored in /root/qdrant-credentials.txt readable only by root
- API authentication enforced - all REST and gRPC requests rejected with 401 without the api-key header
- Qdrant runs as non-root - dedicated qdrant system user, no shell, locked home directory
- Storage owned by qdrant user - 0750 permissions on /var/lib/qdrant, UMask=0027 enforced via systemd
- Telemetry disabled by default - no anonymous usage data leaves the VM
- CVE scan - every image is scanned for vulnerabilities with Trivy before release
- UFW firewall - only ports 6333 (REST), 6334 (gRPC), and 22 (SSH) open; everything else blocked
- fail2ban - SSH brute-force protection
- AppArmor - mandatory access control
OS hardening (CIS Level 1):
- CIS Level 1 hardened - CIS Ubuntu 24.04 LTS Level 1 Benchmark via ansible-lockdown
- auditd - system call auditing for critical paths
- SSH hardening - PasswordAuthentication disabled, key-only access
- Kernel hardening - SYN cookies, ASLR, rp_filter, TCP BBR
- /tmp as tmpfs - nosuid, nodev, noexec
- Azure IMDS endpoints - egress rules pre-configured (169.254.169.254, 168.63.129.16)
Compliance artifacts (inside the VM):
- SBOM - CycloneDX 1.6 at /etc/lynxroute/sbom.json with SHA-256 hash of the Qdrant binary and NTIA-compliant supplier metadata for every component
- CIS Conformance Report - OpenSCAP HTML at /etc/lynxroute/cis-report.html
- Tailored CIS profile - /usr/share/doc/lynxroute/CIS_TAILORED_PROFILE.md
- Server credentials file - /root/qdrant-credentials.txt with public IP, REST/gRPC URLs, Web UI URL, and the per-instance API key
AI-ready out of the box:
- fastembed pre-installed - generate embeddings locally without external API calls
- qdrant-client Python SDK - ready to import in your scripts and notebooks
- Quickstart example - /usr/local/share/qdrant-examples/quickstart.py runs create/upsert/search/delete with semantic embeddings
- Web UI included - browse collections, run queries, inspect payloads
Quick Start
- Deploy VM from Azure Marketplace (Standard_D2s_v3 or larger recommended)
- Open NSG: TCP 6333 and 6334 from your client networks - SSH 22 from your management IPs only
- SSH: ssh -i key.pem <username>@<PUBLIC_IP> (username set during VM creation, default: azureuser)
- Read connection details: sudo cat /root/qdrant-credentials.txt - contains REST URL, gRPC URL, Web UI URL, and the unique API key
- Test the API: curl -H "api-key: $KEY" http://127.0.0.1:6333/healthz
- Run the quickstart: sudo python3 /usr/local/share/qdrant-examples/quickstart.py - creates a collection, inserts vectors with fastembed, runs a semantic search, deletes the collection
- Open the Web UI: http://<PUBLIC_IP>:6333/dashboard - paste the API key when prompted
The API key is unique per VM and is your only authentication credential - keep /root/qdrant-credentials.txt readable by root only. For production, restrict ports 6333 and 6334 to trusted client networks in the NSG.