Loading...
Self-hosting Qdrant with Docker on an Ubuntu Server

Self-hosting Qdrant with Docker on an Ubuntu Server

Jonas Scholz - Co-Founder von sliplane.ioJonas Scholz
13 min

Looking to power AI apps with vector search but want full control over your infrastructure? By self-hosting Qdrant on a Linux Ubuntu server, you can avoid usage-based pricing and ensure your data stays where you want it.

This comprehensive guide will walk you through deploying a production-ready Qdrant instance using Docker and Caddy for automatic HTTPS. You'll learn about security, monitoring, backups, and performance optimization.

Why Self-Host Qdrant?

  • Cost Control: Avoid per-vector pricing and usage-based fees
  • Data Privacy: Keep your vectors and metadata on your own infrastructure
  • Full Control: Configure exactly what you need without platform limitations
  • No Vendor Lock-in: Migrate your data anytime without restrictions
  • Custom Networking: Set up VPNs, custom domains, and advanced firewall rules

Prerequisites

Before we begin, ensure you have:

  • A running Ubuntu Linux server (20.04 LTS or newer recommended)
  • At least 2GB RAM and 2 CPU cores (4GB+ recommended for production)
  • 20GB+ available disk space
  • A domain name pointing to your server (optional but recommended)
  • Basic SSH and command line skills

Want to self-host Qdrant without managing your own server? Deploy it on Sliplane in 45 seconds with built-in HTTPS and volume persistence.

Step 1: Update Your Server

SSH into your Ubuntu server and apply updates:

sudo apt-get update
sudo apt-get upgrade -y

This ensures your server has the latest security patches and packages.

Step 2: Configure Firewall

Since Docker bypasses traditional Linux firewalls like UFW, use your cloud provider's firewall:

  • Hetzner: Cloud Firewall
  • DigitalOcean: Firewall rules in control panel
  • AWS: Security Groups
  • Google Cloud: VPC firewall rules
  • Azure: Network Security Groups

Configure these inbound rules:

  • Port 22 (SSH) - Your IP only
  • Port 80 (HTTP) - Public
  • Port 443 (HTTPS) - Public

Cloud provider firewalls work at the network level before traffic reaches your server, providing better security than host-based firewalls.

Step 3: Docker Installation

Install Docker and dependencies:

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Add Docker's official repo:

echo \
  "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

Install Docker Engine and plugins:

sudo apt-get install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin -y

Verify Docker works:

sudo docker run hello-world

Step 4: Installing Caddy for Automatic HTTPS

Caddy will reverse proxy to Qdrant and handle Let's Encrypt certificates.

Install Caddy:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list

sudo apt update
sudo apt install caddy -y

Edit the Caddyfile config:

sudo nano /etc/caddy/Caddyfile

Use your domain:

yourdomain.com {
    reverse_proxy localhost:6333
}

Or temporarily for local IP testing:

:80 {
    reverse_proxy localhost:6333
}

Restart Caddy:

sudo systemctl restart caddy

Step 5: Running Qdrant with Docker Compose

Create a directory for Qdrant and go into it:

mkdir ~/qdrant
cd ~/qdrant

Create docker-compose.yml:

services:
  qdrant:
    image: qdrant/qdrant:latest
    container_name: qdrant
    restart: unless-stopped
    ports:
      - "6333:6333"  # REST API
      - "6334:6334"  # gRPC API (optional)
    volumes:
      - qdrant_data:/qdrant/storage
      - ./config:/qdrant/config
    environment:
      - QDRANT__SERVICE__API_KEY=your-secret-key-here
      - QDRANT__LOG_LEVEL=INFO
      - QDRANT__SERVICE__HTTP_PORT=6333
      - QDRANT__SERVICE__GRPC_PORT=6334
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:6333/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - qdrant-network

networks:
  qdrant-network:
    driver: bridge

volumes:
  qdrant_data:
    driver: local

Important: Replace your-secret-key-here with a strong, randomly generated API key. Generate one with:

openssl rand -hex 32

If you remove the API key environment variable, Qdrant will run without authentication (not recommended for production).

Create a config directory and optional configuration file:

mkdir config

Create config/production.yaml (optional, for advanced configuration):

service:
  http_port: 6333
  grpc_port: 6334
  enable_cors: true

storage:
  performance:
    max_search_threads: 0  # Use all available CPU cores
    max_optimization_threads: 0

log_level: "INFO"

Start Qdrant:

sudo docker compose up -d

Check that it's running:

sudo docker compose ps
sudo docker compose logs qdrant

Qdrant is now running and accessible on port 6333.

Step 6: Accessing Your Self-Hosted Qdrant Instance

Open your domain in a browser. You should see the Qdrant dashboard at:

https://yourdomain.com/dashboard

Test the API with curl:

# Health check
curl https://yourdomain.com/healthz

# List collections (requires API key)
curl -X GET 'https://yourdomain.com/collections' \
  -H 'api-key: your-secret-key-here'

# Create a test collection
curl -X PUT 'https://yourdomain.com/collections/test' \
  -H 'Content-Type: application/json' \
  -H 'api-key: your-secret-key-here' \
  -d '{
    "vectors": {
      "size": 4,
      "distance": "Cosine"
    }
  }'

Security Hardening

Essential Security Measures

1. Strong API Keys

# Generate a secure 32-byte API key
openssl rand -hex 32

2. Regular Security Updates

# Set up automatic security updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades

3. Fail2ban Protection

sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

4. SSH Key Authentication

# Disable password authentication in /etc/ssh/sshd_config
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart ssh

5. IP Allowlisting

For IP-based access control, configure your cloud provider's firewall to only allow specific IP ranges on ports 80/443. This is more reliable than application-level restrictions.

Monitoring and Maintenance

Health Monitoring

Create a simple health check script:

nano ~/health-check.sh
#!/bin/bash
API_KEY="your-secret-key-here"
QDRANT_URL="https://yourdomain.com"

response=$(curl -s -w "%{http_code}" -X GET "${QDRANT_URL}/healthz" -H "api-key: ${API_KEY}")
http_code="${response: -3}"

if [ "$http_code" = "200" ]; then
    echo "$(date): Qdrant is healthy"
else
    echo "$(date): Qdrant health check failed (HTTP $http_code)"
    # Optional: send alert email or notification
fi

Make it executable and add to cron:

chmod +x ~/health-check.sh
crontab -e
# Add: */5 * * * * /home/ubuntu/health-check.sh >> /var/log/qdrant-health.log

Backup Strategy

For production deployments, we recommend using your cloud provider's built-in backup solutions:

Most cloud providers offer automated volume snapshots:

  • Hetzner: Use Cloud Volume snapshots via the console or API
  • DigitalOcean: Enable automated Droplet backups or Volume snapshots
  • AWS: Use EBS snapshots with lifecycle policies
  • Google Cloud: Use persistent disk snapshots

These snapshots are incremental, crash-consistent, and can be automated with retention policies.

Option 2: Restic + S3 for Cross-Cloud Backups

For a cloud-agnostic backup solution, use Restic with S3-compatible storage:

# Install Restic
sudo apt update
sudo apt install restic -y

# Initialize repository (one time)
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
restic -r s3:s3.amazonaws.com/your-bucket/qdrant-backups init

# Create backup script
nano ~/backup-qdrant.sh
#!/bin/bash
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
RESTIC_REPOSITORY="s3:s3.amazonaws.com/your-bucket/qdrant-backups"

# Stop Qdrant for consistency (optional but recommended)
docker compose stop qdrant

# Backup the Docker volume
restic -r $RESTIC_REPOSITORY backup /var/lib/docker/volumes/qdrant_qdrant_data/_data \
  --tag qdrant \
  --cleanup-cache

# Start Qdrant again
docker compose start qdrant

# Prune old backups (keep last 7 daily, 4 weekly, 12 monthly)
restic -r $RESTIC_REPOSITORY forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

Schedule automated backups:

chmod +x ~/backup-qdrant.sh
crontab -e
# Add: 0 2 * * * /home/ubuntu/backup-qdrant.sh >> /var/log/qdrant-backup.log 2>&1

Restic provides deduplication, encryption, and works with any S3-compatible storage (AWS S3, Backblaze B2, Wasabi, MinIO).

Updating Your Qdrant Installation

To upgrade to the latest version:

cd ~/qdrant
sudo docker compose pull
sudo docker compose up -d

Your data persists across updates thanks to Docker volumes.

Cost Comparison with Other Providers

Self-hosting Qdrant can save significant money:

ProvidervCPURAMStorageMonthly CostSetup Complexity
PineconeN/AN/AN/A$30–300+⭐ Easy
Qdrant Cloud22 GB10 GB$30–49⭐ Easy
Weaviate Cloud22 GB20 GB$25–40⭐ Easy
Sliplane22 GB40 GB€9⭐ Easy
Hetzner (self-hosted)24 GB40 GB€5–8⭐⭐⭐ Advanced
DigitalOcean (self-hosted)22 GB50 GB$12–18⭐⭐⭐ Advanced

Self-hosting avoids per-vector or usage-based pricing, but requires basic system admin skills.

Performance Optimization

System-Level Tuning

Optimize your Ubuntu server for Qdrant:

# Increase file descriptor limits
echo "* soft nofile 65536" | sudo tee -a /etc/security/limits.conf
echo "* hard nofile 65536" | sudo tee -a /etc/security/limits.conf

# Optimize kernel parameters for vector workloads
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
echo "net.core.rmem_max=134217728" | sudo tee -a /etc/sysctl.conf
echo "net.core.wmem_max=134217728" | sudo tee -a /etc/sysctl.conf

# Apply changes
sudo sysctl -p

Docker Resource Management

Monitor your Qdrant container resources:

# Check current resource usage
docker stats qdrant

# View container details
docker inspect qdrant

If you need to limit resources, you can restart the container with limits:

sudo docker compose down
sudo docker run -d \
  --name qdrant \
  --memory="2g" \
  --cpus="1.0" \
  --restart unless-stopped \
  -p 6333:6333 \
  -v qdrant_data:/qdrant/storage \
  -e QDRANT__SERVICE__API_KEY=your-secret-key-here \
  qdrant/qdrant:latest

Troubleshooting Common Issues

Port Conflicts

# Check what's using port 6333
sudo netstat -tlnp | grep :6333
sudo ss -tulpn | grep :6333

Memory Issues

# Monitor Docker container resources
docker stats qdrant

# Check system memory
free -h
htop

Permission Errors

# Fix Docker volume permissions
sudo docker exec qdrant chown -R qdrant:qdrant /qdrant/storage

Log Analysis

# View real-time logs
sudo docker compose logs -f qdrant

# Check last 100 lines
sudo docker compose logs --tail=100 qdrant

# Filter for errors
sudo docker compose logs qdrant | grep -i error

Scaling Considerations

Vertical Scaling

  • Upgrade to a server with more RAM and CPU cores
  • Increase Docker resource limits accordingly
  • Optimize Qdrant configuration for larger datasets

Horizontal Scaling

  • Set up Qdrant cluster with multiple nodes
  • Use a load balancer (HAProxy, Nginx) for request distribution
  • Implement data sharding strategies

What's Included vs. Qdrant Cloud

Self-hosted Qdrant includes:

  • Full vector search capabilities
  • Advanced filtering and hybrid search
  • Web dashboard and REST/gRPC APIs
  • Clustering and replication
  • Snapshots and backups

Qdrant Cloud additional features:

  • Managed backups and monitoring
  • Automatic scaling and updates
  • 24/7 support and SLA guarantees
  • Multi-region deployment

For most use cases, self-hosting provides everything you need. Check the official Qdrant documentation for detailed feature comparisons.

Conclusion

You now have a production-ready Qdrant vector database running on your Ubuntu server! This setup gives you:

  • Complete control over your vector search infrastructure
  • Significant cost savings compared to managed services
  • Data privacy with your vectors staying on your own servers
  • Scalability to handle growing AI workloads

Remember to maintain regular backups, security updates, and monitoring to keep your instance running smoothly.

Want the power of self-hosted Qdrant without managing your own server? Deploy it on Sliplane in 45 seconds with built-in HTTPS and volume persistence.

Welcome to the container cloud

Sliplane makes it simple to deploy containers in the cloud and scale up as you grow. Try it now and get started in minutes!