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
14 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:

Caddyfile
yourdomain.com {
    reverse_proxy localhost:6333
}

Or temporarily for local IP testing:

Caddyfile
: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:

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):

production.yaml
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 (Sliplane Object Storage, AWS S3, Backblaze B2, Wasabi, MinIO).

Need a simple place for backups?

Sliplane Object Storage gives you 250 GB for €5/month, unlimited buckets, no API charges, and no ingress or egress fees. Perfect for app backups, exported data, and generated files.

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 your cloud platform

Sliplane makes it simple to deploy and scale your apps in the cloud. Start with a container or your favorite framework and grow from there. Try it now and get started in minutes!